timeout.go 1.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556
  1. package fx
  2. import (
  3. "context"
  4. "time"
  5. "github.com/tal-tech/go-zero/core/contextx"
  6. )
  7. var (
  8. // ErrCanceled is the error returned when the context is canceled.
  9. ErrCanceled = context.Canceled
  10. // ErrTimeout is the error returned when the context's deadline passes.
  11. ErrTimeout = context.DeadlineExceeded
  12. )
  13. // DoOption defines the method to customize a DoWithTimeout call.
  14. type DoOption func() context.Context
  15. // DoWithTimeout runs fn with timeout control.
  16. func DoWithTimeout(fn func() error, timeout time.Duration, opts ...DoOption) error {
  17. parentCtx := context.Background()
  18. for _, opt := range opts {
  19. parentCtx = opt()
  20. }
  21. ctx, cancel := contextx.ShrinkDeadline(parentCtx, timeout)
  22. defer cancel()
  23. done := make(chan error)
  24. panicChan := make(chan interface{}, 1)
  25. go func() {
  26. defer func() {
  27. if p := recover(); p != nil {
  28. panicChan <- p
  29. }
  30. }()
  31. done <- fn()
  32. close(done)
  33. }()
  34. select {
  35. case p := <-panicChan:
  36. panic(p)
  37. case err := <-done:
  38. return err
  39. case <-ctx.Done():
  40. return ctx.Err()
  41. }
  42. }
  43. // WithContext customizes a DoWithTimeout call with given ctx.
  44. func WithContext(ctx context.Context) DoOption {
  45. return func() context.Context {
  46. return ctx
  47. }
  48. }