timeoutinterceptor.go 964 B

12345678910111213141516171819202122232425262728293031323334353637383940414243
  1. package clientinterceptors
  2. import (
  3. "context"
  4. "time"
  5. "google.golang.org/grpc"
  6. )
  7. // TimeoutInterceptor is an interceptor that controls timeout.
  8. func TimeoutInterceptor(timeout time.Duration) grpc.UnaryClientInterceptor {
  9. return func(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn,
  10. invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {
  11. if timeout <= 0 {
  12. return invoker(ctx, method, req, reply, cc, opts...)
  13. }
  14. ctx, cancel := context.WithTimeout(ctx, timeout)
  15. defer cancel()
  16. // create channel with buffer size 1 to avoid goroutine leak
  17. done := make(chan error, 1)
  18. panicChan := make(chan interface{}, 1)
  19. go func() {
  20. defer func() {
  21. if p := recover(); p != nil {
  22. panicChan <- p
  23. }
  24. }()
  25. done <- invoker(ctx, method, req, reply, cc, opts...)
  26. }()
  27. select {
  28. case p := <-panicChan:
  29. panic(p)
  30. case err := <-done:
  31. return err
  32. case <-ctx.Done():
  33. return ctx.Err()
  34. }
  35. }
  36. }