timeoutinterceptor.go 1.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647
  1. package clientinterceptors
  2. import (
  3. "context"
  4. "time"
  5. "google.golang.org/grpc"
  6. )
  7. // TimeoutCallOption is a call option that controls timeout.
  8. type TimeoutCallOption struct {
  9. grpc.EmptyCallOption
  10. timeout time.Duration
  11. }
  12. // TimeoutInterceptor is an interceptor that controls timeout.
  13. func TimeoutInterceptor(timeout time.Duration) grpc.UnaryClientInterceptor {
  14. return func(ctx context.Context, method string, req, reply any, cc *grpc.ClientConn,
  15. invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {
  16. t := getTimeoutFromCallOptions(opts, timeout)
  17. if t <= 0 {
  18. return invoker(ctx, method, req, reply, cc, opts...)
  19. }
  20. ctx, cancel := context.WithTimeout(ctx, t)
  21. defer cancel()
  22. return invoker(ctx, method, req, reply, cc, opts...)
  23. }
  24. }
  25. // WithCallTimeout returns a call option that controls method call timeout.
  26. func WithCallTimeout(timeout time.Duration) grpc.CallOption {
  27. return TimeoutCallOption{
  28. timeout: timeout,
  29. }
  30. }
  31. func getTimeoutFromCallOptions(opts []grpc.CallOption, defaultTimeout time.Duration) time.Duration {
  32. for _, opt := range opts {
  33. if o, ok := opt.(TimeoutCallOption); ok {
  34. return o.timeout
  35. }
  36. }
  37. return defaultTimeout
  38. }