Skip to content

Commit

Permalink
retry: add new BackoffFuncContext type
Browse files Browse the repository at this point in the history
BackoffFuncContext adds the context parameter, allowing
the retry function access to the contents of the parent
context.

Fixes grpc-ecosystem#171
  • Loading branch information
johanbrandhorst committed Nov 9, 2018
1 parent 498ae20 commit 29e1709
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 4 deletions.
26 changes: 23 additions & 3 deletions retry/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ package grpc_retry
import (
"time"

"golang.org/x/net/context"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
)
Expand All @@ -22,7 +23,9 @@ var (
perCallTimeout: 0, // disabled
includeHeader: true,
codes: DefaultRetriableCodes,
backoffFunc: BackoffLinearWithJitter(50*time.Millisecond /*jitter*/, 0.10),
backoffFunc: BackoffFuncContext(func(ctx context.Context, attempt uint) time.Duration {
return BackoffLinearWithJitter(50*time.Millisecond /*jitter*/, 0.10)(attempt)
}),
}
)

Expand All @@ -34,6 +37,14 @@ var (
// with the next iteration.
type BackoffFunc func(attempt uint) time.Duration

// BackoffFuncContext denotes a family of functions that control the backoff duration between call retries.
//
// They are called with an identifier of the attempt, and should return a time the system client should
// hold off for. If the time returned is longer than the `context.Context.Deadline` of the request
// the deadline of the request takes precedence and the wait will be interrupted before proceeding
// with the next iteration. The context can be used to extract request scoped metadata and context values.
type BackoffFuncContext func(ctx context.Context, attempt uint) time.Duration

// Disable disables the retry behaviour on this call, or this interceptor.
//
// Its semantically the same to `WithMax`
Expand All @@ -48,8 +59,17 @@ func WithMax(maxRetries uint) CallOption {
}}
}

// WithBackoff sets the `BackoffFunc `used to control time between retries.
// WithBackoff sets the `BackoffFunc` used to control time between retries.
func WithBackoff(bf BackoffFunc) CallOption {
return CallOption{applyFunc: func(o *options) {
o.backoffFunc = BackoffFuncContext(func(ctx context.Context, attempt uint) time.Duration {
return bf(attempt)
})
}}
}

// WithBackoffContext sets the `BackoffFuncContext` used to control time between retries.
func WithBackoffContext(bf BackoffFuncContext) CallOption {
return CallOption{applyFunc: func(o *options) {
o.backoffFunc = bf
}}
Expand Down Expand Up @@ -87,7 +107,7 @@ type options struct {
perCallTimeout time.Duration
includeHeader bool
codes []codes.Code
backoffFunc BackoffFunc
backoffFunc BackoffFuncContext
}

// CallOption is a grpc.CallOption that is local to grpc_retry.
Expand Down
2 changes: 1 addition & 1 deletion retry/retry.go
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ func (s *serverStreamingRetryingStream) reestablishStreamAndResendBuffer(callCtx
func waitRetryBackoff(attempt uint, parentCtx context.Context, callOpts *options) error {
var waitTime time.Duration = 0
if attempt > 0 {
waitTime = callOpts.backoffFunc(attempt)
waitTime = callOpts.backoffFunc(parentCtx, attempt)
}
if waitTime > 0 {
logTrace(parentCtx, "grpc_retry attempt: %d, backoff for %v", attempt, waitTime)
Expand Down

0 comments on commit 29e1709

Please sign in to comment.