From 7d2b4230928d83b64235a8c173a49e029990a1ce Mon Sep 17 00:00:00 2001 From: Theodore Tsirpanis Date: Mon, 30 Mar 2026 05:15:52 +0300 Subject: [PATCH] Optimize recursive deletes in S3. We use the `DeleteObjects` API, that allows deleting multiple objects in one request. --- FluentStorage.AWS/Blobs/AwsS3DirectoryBrowser.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/FluentStorage.AWS/Blobs/AwsS3DirectoryBrowser.cs b/FluentStorage.AWS/Blobs/AwsS3DirectoryBrowser.cs index 343b50a..c17a501 100644 --- a/FluentStorage.AWS/Blobs/AwsS3DirectoryBrowser.cs +++ b/FluentStorage.AWS/Blobs/AwsS3DirectoryBrowser.cs @@ -43,7 +43,7 @@ private async Task ListFolderAsync(List container, string path, ListOption Delimiter = options.Recurse ? null : "/" //this tells S3 not to go into the folder recursively }; - // Server side filtering is supported by supplying a FilePrefix + // Server side filtering is supported by supplying a FilePrefix if (!string.IsNullOrEmpty(options.FilePrefix)) { request.Prefix += options.FilePrefix; } @@ -103,7 +103,10 @@ public async Task DeleteRecursiveAsync(string fullPath, CancellationToken cancel if (response?.S3Objects == null) break; - await Task.WhenAll(response.S3Objects.Select(s3 => _client.DeleteObjectAsync(_bucketName, s3.Key, cancellationToken))).ConfigureAwait(false); + await _client.DeleteObjectsAsync(new DeleteObjectsRequest() { + BucketName = _bucketName, + Objects = response.S3Objects.Select(s3 => new KeyVersion() { Key = s3.Key }).ToList() + }, cancellationToken).ConfigureAwait(false); if (response.NextContinuationToken == null) break;