Skip to content

Commit 3834477

Browse files
authored
Call retry callback on retry (#700)
* Move on retry callback to when it retries * the same for streaming * after backoff wait * add test on retry callback on non-retriable errors
1 parent 3f5e2b3 commit 3834477

File tree

2 files changed

+21
-2
lines changed

2 files changed

+21
-2
lines changed

interceptors/retry/retry.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,14 +40,16 @@ func UnaryClientInterceptor(optFuncs ...CallOption) grpc.UnaryClientInterceptor
4040
if err := waitRetryBackoff(attempt, parentCtx, callOpts); err != nil {
4141
return err
4242
}
43+
if attempt > 0 {
44+
callOpts.onRetryCallback(parentCtx, attempt, lastErr)
45+
}
4346
callCtx, cancel := perCallContext(parentCtx, callOpts, attempt)
4447
defer cancel() // Clean up potential resources.
4548
lastErr = invoker(callCtx, method, req, reply, cc, grpcOpts...)
4649
// TODO(mwitkow): Maybe dial and transport errors should be retriable?
4750
if lastErr == nil {
4851
return nil
4952
}
50-
callOpts.onRetryCallback(parentCtx, attempt, lastErr)
5153
if isContextError(lastErr) {
5254
if parentCtx.Err() != nil {
5355
logTrace(parentCtx, "grpc_retry attempt: %d, parent context error: %v", attempt, parentCtx.Err())
@@ -94,6 +96,9 @@ func StreamClientInterceptor(optFuncs ...CallOption) grpc.StreamClientIntercepto
9496
if err := waitRetryBackoff(attempt, parentCtx, callOpts); err != nil {
9597
return nil, err
9698
}
99+
if attempt > 0 {
100+
callOpts.onRetryCallback(parentCtx, attempt, lastErr)
101+
}
97102
var newStreamer grpc.ClientStream
98103
newStreamer, lastErr = streamer(parentCtx, desc, cc, method, grpcOpts...)
99104
if lastErr == nil {
@@ -107,7 +112,6 @@ func StreamClientInterceptor(optFuncs ...CallOption) grpc.StreamClientIntercepto
107112
}
108113
return retryingStreamer, nil
109114
}
110-
callOpts.onRetryCallback(parentCtx, attempt, lastErr)
111115
if isContextError(lastErr) {
112116
if parentCtx.Err() != nil {
113117
logTrace(parentCtx, "grpc_retry attempt: %d, parent context error: %v", attempt, parentCtx.Err())

interceptors/retry/retry_test.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,21 @@ func (s *RetrySuite) TestUnary_OnRetryCallbackCalled() {
204204
require.EqualValues(s.T(), 2, retryCallbackCount, "two retry callbacks should be called")
205205
}
206206

207+
func (s *RetrySuite) TestUnary_OnRetryCallbackNotCalledOnNonRetriableError() {
208+
retryCallbackCount := 0
209+
210+
s.srv.resetFailingConfiguration(3, codes.Internal, noSleep) // see retriable_errors
211+
out, err := s.Client.Ping(s.SimpleCtx(), testpb.GoodPing,
212+
WithOnRetryCallback(func(ctx context.Context, attempt uint, err error) {
213+
retryCallbackCount++
214+
}),
215+
)
216+
217+
require.Error(s.T(), err, "should result in an error")
218+
require.Nil(s.T(), out, "out should be nil")
219+
require.EqualValues(s.T(), 0, retryCallbackCount, "no retry callbacks should be called")
220+
}
221+
207222
func (s *RetrySuite) TestServerStream_SucceedsOnRetriableError() {
208223
s.srv.resetFailingConfiguration(3, codes.DataLoss, noSleep) // see retriable_errors
209224
stream, err := s.Client.PingList(s.SimpleCtx(), testpb.GoodPingList)

0 commit comments

Comments
 (0)