S3 is pretty resilient, and the built in retry handling is probably sufficient as it should notice closed connections and timeouts which are the most likely sort of failure modes
(ctx context.Context, err error)
| 1274 | // as it should notice closed connections and timeouts which are the most likely |
| 1275 | // sort of failure modes |
| 1276 | func (f *Fs) shouldRetry(ctx context.Context, err error) (bool, error) { |
| 1277 | if fserrors.ContextError(ctx, &err) { |
| 1278 | return false, err |
| 1279 | } |
| 1280 | // https://github.com/aws/aws-sdk-go-v2/blob/main/CHANGELOG.md#error-handling |
| 1281 | // If this is an awserr object, try and extract more useful information to determine if we should retry |
| 1282 | var awsError smithy.APIError |
| 1283 | if errors.As(err, &awsError) { |
| 1284 | // Simple case, check the original embedded error in case it's generically retryable |
| 1285 | if fserrors.ShouldRetry(awsError) { |
| 1286 | return true, err |
| 1287 | } |
| 1288 | // If it is a timeout then we want to retry that |
| 1289 | if awsError.ErrorCode() == "RequestTimeout" { |
| 1290 | return true, err |
| 1291 | } |
| 1292 | } |
| 1293 | // Check http status code if available |
| 1294 | if httpStatusCode := getHTTPStatusCode(err); httpStatusCode > 0 { |
| 1295 | // 301 if wrong region for bucket - can only update if running from a bucket |
| 1296 | if f.rootBucket != "" { |
| 1297 | if httpStatusCode == http.StatusMovedPermanently { |
| 1298 | urfbErr := f.updateRegionForBucket(ctx, f.rootBucket) |
| 1299 | if urfbErr != nil { |
| 1300 | fs.Errorf(f, "Failed to update region for bucket: %v", urfbErr) |
| 1301 | return false, err |
| 1302 | } |
| 1303 | return true, err |
| 1304 | } |
| 1305 | } |
| 1306 | if slices.Contains(retryErrorCodes, httpStatusCode) { |
| 1307 | return true, err |
| 1308 | } |
| 1309 | } |
| 1310 | // Ok, not an awserr, check for generic failure conditions |
| 1311 | return fserrors.ShouldRetry(err), err |
| 1312 | } |
| 1313 | |
| 1314 | // parsePath parses a remote 'url' |
| 1315 | func parsePath(path string) (root string) { |