From 572c1079a59c4cefff99fb49e4291fe25f0880a5 Mon Sep 17 00:00:00 2001 From: Nick Craig-Wood Date: Mon, 2 Dec 2019 16:02:38 +0000 Subject: [PATCH] fserrors: Make a new NoLowLevelRetry error and don't retry them #3777 --- fs/fserrors/error.go | 52 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/fs/fserrors/error.go b/fs/fserrors/error.go index c1aa31e89..aa3e6067f 100644 --- a/fs/fserrors/error.go +++ b/fs/fserrors/error.go @@ -178,6 +178,53 @@ func IsNoRetryError(err error) (isNoRetry bool) { return } +// NoLowLevelRetrier is an optional interface for error as to whether +// the operation should not be retried at a low level. +// +// NoLowLevelRetry errors won't be retried by low level retry loops. +type NoLowLevelRetrier interface { + error + NoLowLevelRetry() bool +} + +// wrappedNoLowLevelRetryError is an error wrapped so it will satisfy the +// NoLowLevelRetrier interface and return true +type wrappedNoLowLevelRetryError struct { + error +} + +// NoLowLevelRetry interface +func (err wrappedNoLowLevelRetryError) NoLowLevelRetry() bool { + return true +} + +// Check interface +var _ NoLowLevelRetrier = wrappedNoLowLevelRetryError{error(nil)} + +// NoLowLevelRetryError makes an error which indicates the sync +// shouldn't be low level retried. +func NoLowLevelRetryError(err error) error { + return wrappedNoLowLevelRetryError{err} +} + +// Cause returns the underlying error +func (err wrappedNoLowLevelRetryError) Cause() error { + return err.error +} + +// IsNoLowLevelRetryError returns true if err conforms to the NoLowLevelRetry +// interface and calling the NoLowLevelRetry method returns true. +func IsNoLowLevelRetryError(err error) (isNoLowLevelRetry bool) { + errors.Walk(err, func(err error) bool { + if r, ok := err.(NoLowLevelRetrier); ok { + isNoLowLevelRetry = r.NoLowLevelRetry() + return true + } + return false + }) + return +} + // RetryAfter is an optional interface for error as to whether the // operation should be retried after a given delay // @@ -345,6 +392,11 @@ func ShouldRetry(err error) bool { return false } + // If error has been marked to NoLowLevelRetry then don't retry + if IsNoLowLevelRetryError(err) { + return false + } + // Find root cause if available retriable, err := Cause(err) if retriable {