s3api: remove the duplicated listing retry helpers left by overlapping merges

This commit is contained in:
Chris Lu
2026-08-23 00:26:02 -07:00
parent c58795354a
commit 8d8a25b1cf
2 changed files with 2 additions and 57 deletions
+2 -11
View File
@@ -1037,13 +1037,7 @@ func (s3a *S3ApiServer) listMultipartUploads(input *s3.ListMultipartUploadsInput
IsTruncated: aws.Bool(false),
}
// A blip on the way to the filer, either on the ListEntries call or on the
// stream receives that follow it, used to fail the whole listing; replay it
// a bounded number of times before giving up.
uploadsFolder := s3a.genUploadsFolder(*input.Bucket)
entries, _, err := listWithRetry(uploadsFolder, func() ([]*filer_pb.Entry, bool, error) {
return s3a.list(uploadsFolder, "", *input.UploadIdMarker, false, math.MaxInt32)
})
entries, _, err := s3a.list(s3a.genUploadsFolder(*input.Bucket), "", *input.UploadIdMarker, false, math.MaxInt32)
if err != nil {
// A missing .uploads folder normally lists as empty with no error; a
// store that reports it as not-found still means an empty list.
@@ -1110,10 +1104,7 @@ func (s3a *S3ApiServer) listObjectParts(input *s3.ListPartsInput) (output *ListP
StorageClass: aws.String("STANDARD"),
}
partsFolder := s3a.genUploadsFolder(*input.Bucket) + "/" + *input.UploadId
entries, isLast, err := listWithRetry(partsFolder, func() ([]*filer_pb.Entry, bool, error) {
return s3a.list(partsFolder, "", fmt.Sprintf("%04d%s", *input.PartNumberMarker, multipartExt), false, uint32(*input.MaxParts))
})
entries, isLast, err := s3a.list(s3a.genUploadsFolder(*input.Bucket)+"/"+*input.UploadId, "", fmt.Sprintf("%04d%s", *input.PartNumberMarker, multipartExt), false, uint32(*input.MaxParts))
if err != nil {
// A store that reports the missing upload directory as not-found means
// the upload is gone (completed or aborted), not a store error.
-46
View File
@@ -83,52 +83,6 @@ func listWithRetry(parentDirectoryPath string, doList func() (entries []*filer_p
}
// Bounds for replaying a listing that failed with a transient error. A listing
// is a read with no side effects and each attempt opens a new stream and
// collects into a fresh slice, so replaying it can neither duplicate nor drop
// entries. The bound keeps a filer that is genuinely down from stalling the S3
// request: at most two extra attempts and 300ms of added wait.
const (
listRetryAttempts = 3
listRetryInitialBackoff = 100 * time.Millisecond
)
// isRetryableListError reports whether a failed listing is worth replaying. A
// not-found answer is authoritative and every other non-transient error is a
// real failure, so both must reach the caller unchanged: the point is to
// survive a blip, not to hide a broken store.
func isRetryableListError(err error) bool {
if err == nil || isFilerNotFound(err) {
return false
}
if status.Code(err) == codes.Unavailable {
return true
}
// DoSeaweedListWithSnapshot wraps a failed ListEntries call with %v, which
// drops the gRPC status from the error chain, so for that path the message
// is all that is left to classify on.
return util.IsTransientError(err)
}
// listWithRetry replays doList while the filer answers with a transient error.
// Both failure points reported for multipart listing, the ListEntries call
// itself and the stream.Recv that follows it, surface as a plain error out of
// filer_pb.List, so a single retry point above it covers both.
func listWithRetry(parentDirectoryPath string, doList func() (entries []*filer_pb.Entry, isLast bool, err error)) (entries []*filer_pb.Entry, isLast bool, err error) {
backoff := listRetryInitialBackoff
for attempt := 1; ; attempt++ {
entries, isLast, err = doList()
if err == nil || attempt >= listRetryAttempts || !isRetryableListError(err) {
return entries, isLast, err
}
glog.V(1).Infof("list %s attempt %d/%d hit a transient error, retrying in %v: %v", parentDirectoryPath, attempt, listRetryAttempts, backoff, err)
time.Sleep(backoff)
backoff *= 2
}
}
func (s3a *S3ApiServer) rm(parentDirectoryPath, entryName string, isDeleteData, isRecursive bool) error {
return s3a.WithFilerClient(false, func(client filer_pb.SeaweedFilerClient) error {