func RetryUnaryClientInterceptor(optFuncs ...CallOption) grpc.UnaryClientInterceptor {
	intOpts := reuseOrNewWithCallOptions(defaultRetryOptions, optFuncs)
	return func(parentCtx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {
		grpcOpts, retryOpts := filterCallOptions(opts)
		callOpts := reuseOrNewWithCallOptions(intOpts, retryOpts)
		if callOpts.max == 0 {
			return invoker(parentCtx, method, req, reply, cc, grpcOpts...)
		}
		var lastErr error
		for attempt := uint(0); attempt < callOpts.max; attempt++ {
			callCtx, cancel := perCallContext(parentCtx, callOpts, attempt)
			func() {
				defer cancel()
				lastErr = invoker(callCtx, method, req, reply, cc, grpcOpts...)
			}()
			if lastErr == nil {
				return nil
			}
			if isContextError(lastErr) {
				if parentCtx.Err() != nil {
					// its the parent context deadline or cancellation.
					return lastErr
				} else if callOpts.perCallTimeout != 0 {
					// We have set a perCallTimeout in the retry middleware, which would result in a context error if
					// the deadline was exceeded, in which case try again.
					continue
				}
			}
			if !isRetriable(lastErr, callOpts) {
				return lastErr
			}
			if err := waitRetryBackoff(parentCtx, attempt, callOpts); err != nil {
				return err
			}
		}
		return lastErr
	}
}
// RetryUnaryClientInterceptor returns a new retrying unary client interceptor.
//
// The default configuration of the interceptor is to not retry *at all*. This behavior can be
// changed through options (e.g. WithMax) on creation of the interceptor or on call (through grpc.CallOptions).
RetryUnaryClientInterceptor returns a new retrying unary client interceptor.

The default configuration of the interceptor is to not retry *at all*. This behavior can be
changed through options  on creation of the interceptor or on call (through grpc.CallOptions).
// RetryUnaryClientInterceptor returns a new retrying unary client interceptor . // // The default configuration of the interceptor is to not retry * at all * . This behavior can be // changed through options ( e . g . WithMax ) on creation of the interceptor or on call ( through grpc . CallOptions ) .
func RetryUnaryClientInterceptor(optFuncs ...CallOption) grpc.UnaryClientInterceptor {
	intOpts := reuseOrNewWithCallOptions(defaultRetryOptions, optFuncs)
	return func(parentCtx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {
		grpcOpts, retryOpts := filterCallOptions(opts)
		callOpts := reuseOrNewWithCallOptions(intOpts, retryOpts)
		if callOpts.max == 0 {
			return invoker(parentCtx, method, req, reply, cc, grpcOpts...)
		}
		var lastErr error
		for attempt := uint(0); attempt < callOpts.max; attempt++ {
			callCtx, cancel := perCallContext(parentCtx, callOpts, attempt)
			func() {
				defer cancel()
				lastErr = invoker(callCtx, method, req, reply, cc, grpcOpts...)
			}()
			if lastErr == nil {
				return nil
			}
			if isContextError(lastErr) {
				if parentCtx.Err() != nil {
					return lastErr
				} else if callOpts.perCallTimeout != 0 {
					continue
				}
			}
			if !isRetriable(lastErr, callOpts) {
				return lastErr
			}
			if err := waitRetryBackoff(parentCtx, attempt, callOpts); err != nil {
				return err
			}
		}
		return lastErr
	}
}
func RetryUnaryClientInterceptor ( optFuncs ... CallOption ) grpc . UnaryClientInterceptor { intOpts := reuseOrNewWithCallOptions ( defaultRetryOptions , optFuncs ) return func ( parentCtx context . Context , method string , req , reply interface { } , cc * grpc . ClientConn , invoker grpc . UnaryInvoker , opts ... grpc . CallOption ) error { grpcOpts , retryOpts := filterCallOptions ( opts ) callOpts := reuseOrNewWithCallOptions ( intOpts , retryOpts ) if callOpts . max == 0 { return invoker ( parentCtx , method , req , reply , cc , grpcOpts ... ) } var lastErr error for attempt := uint ( 0 ) ; attempt < callOpts . max ; attempt ++ { callCtx , cancel := perCallContext ( parentCtx , callOpts , attempt ) func ( ) { defer cancel ( ) lastErr = invoker ( callCtx , method , req , reply , cc , grpcOpts ... ) } ( ) if lastErr == nil { return nil } if isContextError ( lastErr ) { if parentCtx . Err ( ) != nil { return lastErr } else if callOpts . perCallTimeout != 0 { continue } } if ! isRetriable ( lastErr , callOpts ) { return lastErr } if err := waitRetryBackoff ( parentCtx , attempt , callOpts ) ; err != nil { return err } } return lastErr } }
RetryUnaryClientInterceptor returns a new retrying unary client interceptor.
RetryUnaryClientInterceptor returns a new retrying unary client interceptor .
// its the parent context deadline or cancellation. // We have set a perCallTimeout in the retry middleware, which would result in a context error if // the deadline was exceeded, in which case try again.