timeoutinterceptor.go 1013 B

1234567891011121314151617181920212223242526272829303132333435363738394041424344
  1. package clientinterceptors
  2. import (
  3. "context"
  4. "time"
  5. "github.com/tal-tech/go-zero/core/contextx"
  6. "google.golang.org/grpc"
  7. )
  8. // TimeoutInterceptor is an interceptor that controls timeout.
  9. func TimeoutInterceptor(timeout time.Duration) grpc.UnaryClientInterceptor {
  10. return func(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn,
  11. invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {
  12. if timeout <= 0 {
  13. return invoker(ctx, method, req, reply, cc, opts...)
  14. }
  15. ctx, cancel := contextx.ShrinkDeadline(ctx, timeout)
  16. defer cancel()
  17. // create channel with buffer size 1 to avoid goroutine leak
  18. done := make(chan error, 1)
  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 <- invoker(ctx, method, req, reply, cc, opts...)
  27. }()
  28. select {
  29. case p := <-panicChan:
  30. panic(p)
  31. case err := <-done:
  32. return err
  33. case <-ctx.Done():
  34. return ctx.Err()
  35. }
  36. }
  37. }