Merge pull request #133 from ynori7/master

Adding the ability to specify a function to check if micro should retry a failed rpc call
This commit is contained in:
Asim Aslam 2016-11-07 16:50:45 +00:00 committed by GitHub
commit 3b75e94e02
4 changed files with 44 additions and 0 deletions

View File

@ -68,6 +68,8 @@ var (
DefaultClient Client = newRpcClient() DefaultClient Client = newRpcClient()
// DefaultBackoff is the default backoff function for retries // DefaultBackoff is the default backoff function for retries
DefaultBackoff = exponentialBackoff DefaultBackoff = exponentialBackoff
// DefaultRetry is the default check-for-retry function for retries
DefaultRetry = alwaysRetry
// DefaultRetries is the default number of times a request is tried // DefaultRetries is the default number of times a request is tried
DefaultRetries = 1 DefaultRetries = 1
// DefaultRequestTimeout is the default request timeout // DefaultRequestTimeout is the default request timeout

View File

@ -43,6 +43,8 @@ type CallOptions struct {
// Backoff func // Backoff func
Backoff BackoffFunc Backoff BackoffFunc
// Check if retriable func
Retry RetryFunc
// Transport Dial Timeout // Transport Dial Timeout
DialTimeout time.Duration DialTimeout time.Duration
// Number of Call attempts // Number of Call attempts
@ -74,6 +76,7 @@ func newOptions(options ...Option) Options {
Codecs: make(map[string]codec.NewCodec), Codecs: make(map[string]codec.NewCodec),
CallOptions: CallOptions{ CallOptions: CallOptions{
Backoff: DefaultBackoff, Backoff: DefaultBackoff,
Retry: DefaultRetry,
Retries: DefaultRetries, Retries: DefaultRetries,
RequestTimeout: DefaultRequestTimeout, RequestTimeout: DefaultRequestTimeout,
DialTimeout: transport.DefaultDialTimeout, DialTimeout: transport.DefaultDialTimeout,
@ -221,6 +224,14 @@ func WithBackoff(fn BackoffFunc) CallOption {
} }
} }
// WithRetry is a CallOption which overrides that which
// set in Options.CallOptions
func WithRetry(fn RetryFunc) CallOption {
return func(o *CallOptions) {
o.Retry = fn
}
}
// WithRetries is a CallOption which overrides that which // WithRetries is a CallOption which overrides that which
// set in Options.CallOptions // set in Options.CallOptions
func WithRetries(i int) CallOption { func WithRetries(i int) CallOption {

11
client/retry.go Normal file
View File

@ -0,0 +1,11 @@
package client
import "golang.org/x/net/context"
// note that returning either true or a non-nil error will result in the call not being retried
type RetryFunc func(ctx context.Context, req Request, retryCount int, err error) (bool, error)
// always retry on error
func alwaysRetry(ctx context.Context, req Request, retryCount int, err error) (bool, error) {
return true, nil
}

View File

@ -299,6 +299,16 @@ func (r *rpcClient) Call(ctx context.Context, request Request, response interfac
if err == nil { if err == nil {
return nil return nil
} }
retry, rerr := callOpts.Retry(ctx, request, i, err)
if rerr != nil {
return rerr
}
if !retry {
return err
}
gerr = err gerr = err
} }
} }
@ -400,6 +410,16 @@ func (r *rpcClient) Stream(ctx context.Context, request Request, opts ...CallOpt
if rsp.err == nil { if rsp.err == nil {
return rsp.stream, nil return rsp.stream, nil
} }
retry, rerr := callOpts.Retry(ctx, request, i, rsp.err)
if rerr != nil {
return nil, rerr
}
if !retry {
return nil, rsp.err
}
grr = rsp.err grr = rsp.err
} }
} }