From 99c499b55f85904dfee17bce73b41dff53d72f2d Mon Sep 17 00:00:00 2001 From: Stephan Zeissler Date: Thu, 29 Jan 2015 18:05:30 +0100 Subject: [PATCH] Initial changes to make it usable a lib --- README.md | 17 ++++++++++++++++ options.go | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++++ retry.go | 57 +++++------------------------------------------------- 3 files changed, 77 insertions(+), 52 deletions(-) create mode 100644 README.md create mode 100644 options.go diff --git a/README.md b/README.md new file mode 100644 index 0000000..0f23259 --- /dev/null +++ b/README.md @@ -0,0 +1,17 @@ +retry-go +======== + +Small helper library to retry operations automatically on certain errors. + +## Usage + +``` +retry.Do(someOp, retry.Timeout(15 * time.Second)) +``` + +// The following options are supported: +// * RetryChecker(func(err error) bool) - If this func returns true for the returned error, the operation is tried again +// * MaxTries(int) - Maximum number of calls to op() before aborting with MaxRetriesReached +// * Timeout(time.Duration) - Maximum number of time to try to perform this op before aborting with TimeoutReached +// * Sleep(time.Duration) - time to sleep after error failed op() +// \ No newline at end of file diff --git a/options.go b/options.go new file mode 100644 index 0000000..d7d142a --- /dev/null +++ b/options.go @@ -0,0 +1,55 @@ +package retry + +import ( + "time" +) + +type RetryOption func(options *retryOptions) + +// Timeout specifies the maximum time that should be used before aborting the retry loop. +// Note that this does not abort the operation in progress. +func Timeout(d time.Duration) RetryOption { + return func(options *retryOptions) { + options.Timeout = d + } +} + +// MaxTries specifies the maximum number of times op will be called by Do(). +func MaxTries(tries int) RetryOption { + return func(options *retryOptions) { + options.MaxTries = tries + } +} + +// RetryChecker defines whether the given error is an error that can be retried. +func RetryChecker(checker func(err error) bool) RetryOption { + return func(options *retryOptions) { + options.Checker = checker + } +} + +func Sleep(d time.Duration) RetryOption { + return func(options *retryOptions) { + options.Sleep = d + } +} + +type retryOptions struct { + Timeout time.Duration + MaxTries int + Checker func(err error) bool + Sleep time.Duration +} + +func newRetryOptions(options ...RetryOption) retryOptions { + state := retryOptions{ + Timeout: DefaultTimeout, + MaxTries: DefaultMaxTries, + Retryer: errgo.Any, + } + + for _, option := range options { + option(&state) + } + return state +} diff --git a/retry.go b/retry.go index d63e78b..96ab48f 100644 --- a/retry.go +++ b/retry.go @@ -1,4 +1,4 @@ -package service +package retry import ( "time" @@ -16,58 +16,11 @@ var ( MaxRetriesReached = errgo.New("Operation aborted. To many errors.") ) -type retryOptions struct { - Timeout time.Duration - MaxTries int - Retryer func(err error) bool - Sleep time.Duration -} - -type RetryOption func(options *retryOptions) - -func RetryTimeout(d time.Duration) RetryOption { - return func(options *retryOptions) { - options.Timeout = d - } -} - -func MaxTries(tries int) RetryOption { - return func(options *retryOptions) { - options.MaxTries = tries - } -} - -// Retryer defines whether the given error is an error that can be retried. -func Retryer(retryer func(err error) bool) RetryOption { - return func(options *retryOptions) { - options.Retryer = retryer - } -} - -func Sleep(d time.Duration) RetryOption { - return func(options *retryOptions) { - options.Sleep = d - } -} - -func newRetryOptions(options ...RetryOption) retryOptions { - state := retryOptions{ - Timeout: DefaultTimeout, - MaxTries: DefaultMaxTries, - Retryer: errgo.Any, - } - - for _, option := range options { - option(&state) - } - return state -} - -// retry performs the given operation. Based on the options, it can retry the operation, +// Do performs the given operation. Based on the options, it can retry the operation, // if it failed. // // The following options are supported: -// * Retryer(func(err error) bool) - If this func returns true for the returned error, the operation is tried again +// * RetryChecker(func(err error) bool) - If this func returns true for the returned error, the operation is tried again // * MaxTries(int) - Maximum number of calls to op() before aborting with MaxRetriesReached // * Timeout(time.Duration) - Maximum number of time to try to perform this op before aborting with TimeoutReached // * Sleep(time.Duration) - time to sleep after error failed op() @@ -78,7 +31,7 @@ func newRetryOptions(options ...RetryOption) retryOptions { // Retryer = errgo.Any // Sleep = No sleep // -func retry(op func() error, retryOptions ...RetryOption) error { +func Do(op func() error, retryOptions ...RetryOption) error { options := newRetryOptions(retryOptions...) timeout := time.After(options.Timeout) @@ -96,7 +49,7 @@ func retry(op func() error, retryOptions ...RetryOption) error { lastError := op() if lastError != nil { - if options.Retryer != nil && options.Retryer(lastError) { + if options.Checker != nil && options.Checker(lastError) { // Check max retries if tryCounter >= options.MaxTries { return errgo.WithCausef(lastError, MaxRetriesReached, "Tries %d > %d", tryCounter, options.MaxTries)