diff --git a/internal/backend/backend.go b/internal/backend/backend.go index aa9920f9b..102322c4f 100644 --- a/internal/backend/backend.go +++ b/internal/backend/backend.go @@ -38,7 +38,9 @@ type Backend interface { // Load runs fn with a reader that yields the contents of the file at h at the // given offset. If length is larger than zero, only a portion of the file - // is read. + // is read. If the length is larger than zero and the file is too short to return + // the requested length bytes, then an error MUST be returned that is recognized + // by IsPermanentError(). // // The function fn may be called multiple times during the same Load invocation // and therefore must be idempotent. @@ -66,6 +68,12 @@ type Backend interface { // for unwrapping it. IsNotExist(err error) bool + // IsPermanentError returns true if the error can very likely not be resolved + // by retrying the operation. Backends should return true if the file is missing, + // the requested range does not (completely) exist in the file or the user is + // not authorized to perform the requested operation. + IsPermanentError(err error) bool + // Delete removes all data in the backend. Delete(ctx context.Context) error } diff --git a/internal/backend/dryrun/dry_backend.go b/internal/backend/dryrun/dry_backend.go index b3db0210f..c17b240fa 100644 --- a/internal/backend/dryrun/dry_backend.go +++ b/internal/backend/dryrun/dry_backend.go @@ -72,6 +72,10 @@ func (be *Backend) IsNotExist(err error) bool { return be.b.IsNotExist(err) } +func (be *Backend) IsPermanentError(err error) bool { + return be.b.IsPermanentError(err) +} + func (be *Backend) List(ctx context.Context, t backend.FileType, fn func(backend.FileInfo) error) error { return be.b.List(ctx, t, fn) } diff --git a/internal/backend/mock/backend.go b/internal/backend/mock/backend.go index 57b1ede19..bd8c6d43b 100644 --- a/internal/backend/mock/backend.go +++ b/internal/backend/mock/backend.go @@ -13,6 +13,7 @@ import ( type Backend struct { CloseFn func() error IsNotExistFn func(err error) bool + IsPermanentErrorFn func(err error) bool SaveFn func(ctx context.Context, h backend.Handle, rd backend.RewindReader) error OpenReaderFn func(ctx context.Context, h backend.Handle, length int, offset int64) (io.ReadCloser, error) StatFn func(ctx context.Context, h backend.Handle) (backend.FileInfo, error) @@ -83,6 +84,14 @@ func (m *Backend) IsNotExist(err error) bool { return m.IsNotExistFn(err) } +func (m *Backend) IsPermanentError(err error) bool { + if m.IsPermanentErrorFn == nil { + return false + } + + return m.IsPermanentErrorFn(err) +} + // Save data in the backend. func (m *Backend) Save(ctx context.Context, h backend.Handle, rd backend.RewindReader) error { if m.SaveFn == nil {