NewRateLimitRetrier creates a UnaryClientInterceptor which retries with backoff the calls from invoker when the executed RPC is rate limited.
(cfg backoff.Config)
| 14 | // NewRateLimitRetrier creates a UnaryClientInterceptor which retries with backoff |
| 15 | // the calls from invoker when the executed RPC is rate limited. |
| 16 | func NewRateLimitRetrier(cfg backoff.Config) grpc.UnaryClientInterceptor { |
| 17 | return func(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error { |
| 18 | backoff := backoff.New(ctx, cfg) |
| 19 | var err error |
| 20 | for backoff.Ongoing() { |
| 21 | err = invoker(ctx, method, req, reply, cc, opts...) |
| 22 | if err == nil { |
| 23 | return nil |
| 24 | } |
| 25 | |
| 26 | // Only ResourceExhausted statuses are handled as signals of being rate limited, |
| 27 | // following the implementation of package's RateLimiter interceptor. |
| 28 | // All other errors are propogated as-is upstream. |
| 29 | if status.Code(err) != codes.ResourceExhausted { |
| 30 | return err |
| 31 | } |
| 32 | |
| 33 | backoff.Wait() |
| 34 | } |
| 35 | return errors.Join(err, backoff.Err()) |
| 36 | } |
| 37 | } |
no test coverage detected