make retry code context-aware.

detect cancellation in backend, so that retry code does not keep trying
once user has hit ^c

gh-1434
This commit is contained in:
George Armhold 2017-12-01 07:46:20 -05:00
parent d886cb5c27
commit be24237063
1 changed files with 12 additions and 6 deletions

View File

@ -33,15 +33,21 @@ func NewRetryBackend(be restic.Backend, maxTries int, report func(string, error,
} }
} }
func (be *RetryBackend) retry(msg string, f func() error) error { func (be *RetryBackend) retry(ctx context.Context, msg string, f func() error) error {
return backoff.RetryNotify(f, err := backoff.RetryNotify(f,
backoff.WithMaxTries(backoff.NewExponentialBackOff(), uint64(be.MaxTries)), backoff.WithContext(backoff.WithMaxTries(backoff.NewExponentialBackOff(), uint64(be.MaxTries)), ctx),
func(err error, d time.Duration) { func(err error, d time.Duration) {
if be.Report != nil { if be.Report != nil {
be.Report(msg, err, d) be.Report(msg, err, d)
} }
}, },
) )
if errors.Cause(err) == context.Canceled {
return nil
}
return err
} }
// Save stores the data in the backend under the given handle. // Save stores the data in the backend under the given handle.
@ -60,7 +66,7 @@ func (be *RetryBackend) Save(ctx context.Context, h restic.Handle, rd io.Reader)
return errors.Errorf("reader is not at the beginning (pos %v)", pos) return errors.Errorf("reader is not at the beginning (pos %v)", pos)
} }
return be.retry(fmt.Sprintf("Save(%v)", h), func() error { return be.retry(ctx, fmt.Sprintf("Save(%v)", h), func() error {
_, err := seeker.Seek(0, io.SeekStart) _, err := seeker.Seek(0, io.SeekStart)
if err != nil { if err != nil {
return err return err
@ -87,7 +93,7 @@ func (be *RetryBackend) Save(ctx context.Context, h restic.Handle, rd io.Reader)
// is returned. rd must be closed after use. If an error is returned, the // is returned. rd must be closed after use. If an error is returned, the
// ReadCloser must be nil. // ReadCloser must be nil.
func (be *RetryBackend) Load(ctx context.Context, h restic.Handle, length int, offset int64) (rd io.ReadCloser, err error) { func (be *RetryBackend) Load(ctx context.Context, h restic.Handle, length int, offset int64) (rd io.ReadCloser, err error) {
err = be.retry(fmt.Sprintf("Load(%v, %v, %v)", h, length, offset), err = be.retry(ctx, fmt.Sprintf("Load(%v, %v, %v)", h, length, offset),
func() error { func() error {
var innerError error var innerError error
rd, innerError = be.Backend.Load(ctx, h, length, offset) rd, innerError = be.Backend.Load(ctx, h, length, offset)
@ -99,7 +105,7 @@ func (be *RetryBackend) Load(ctx context.Context, h restic.Handle, length int, o
// Stat returns information about the File identified by h. // Stat returns information about the File identified by h.
func (be *RetryBackend) Stat(ctx context.Context, h restic.Handle) (fi restic.FileInfo, err error) { func (be *RetryBackend) Stat(ctx context.Context, h restic.Handle) (fi restic.FileInfo, err error) {
err = be.retry(fmt.Sprintf("Stat(%v)", h), err = be.retry(ctx, fmt.Sprintf("Stat(%v)", h),
func() error { func() error {
var innerError error var innerError error
fi, innerError = be.Backend.Stat(ctx, h) fi, innerError = be.Backend.Stat(ctx, h)