timeout.go 824 B

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849
  1. package fx
  2. import (
  3. "context"
  4. "time"
  5. )
  6. var (
  7. ErrCanceled = context.Canceled
  8. ErrTimeout = context.DeadlineExceeded
  9. )
  10. type FxOption func() context.Context
  11. func DoWithTimeout(fn func() error, timeout time.Duration, opts ...FxOption) error {
  12. parentCtx := context.Background()
  13. for _, opt := range opts {
  14. parentCtx = opt()
  15. }
  16. ctx, cancel := context.WithTimeout(parentCtx, timeout)
  17. defer cancel()
  18. done := make(chan error)
  19. panicChan := make(chan interface{}, 1)
  20. go func() {
  21. defer func() {
  22. if p := recover(); p != nil {
  23. panicChan <- p
  24. }
  25. }()
  26. done <- fn()
  27. close(done)
  28. }()
  29. select {
  30. case p := <-panicChan:
  31. panic(p)
  32. case err := <-done:
  33. return err
  34. case <-ctx.Done():
  35. return ctx.Err()
  36. }
  37. }
  38. func WithContext(ctx context.Context) FxOption {
  39. return func() context.Context {
  40. return ctx
  41. }
  42. }