@@ -21,19 +21,12 @@ import 'package:retry/retry.dart';
2121
2222import 'configuration.dart' ;
2323import 'utils.dart'
24- show
25- contentType,
26- jsonUtf8Encoder,
27- retryAsync,
28- ByteArrayEqualsExt,
29- DeleteCounts;
24+ show contentType, jsonUtf8Encoder, ByteArrayEqualsExt, DeleteCounts;
3025import 'versions.dart' as versions;
3126
3227final _gzip = GZipCodec ();
3328final _logger = Logger ('shared.storage' );
3429
35- const _retryStatusCodes = < int > {502 , 503 , 504 };
36-
3730/// Additional methods on the storage service.
3831extension StorageExt on Storage {
3932 /// Verifies bucket existence and access.
@@ -115,18 +108,19 @@ extension BucketExt on Bucket {
115108 }
116109
117110 /// Deletes [name] if it exists, ignores 404 otherwise.
118- Future <void > tryDelete (String name) async {
119- return await retry (
111+ Future <bool > tryDeleteWithRetry (String name) async {
112+ return await _retry (
120113 () async {
121114 try {
122- return await delete (name);
115+ await delete (name);
116+ return true ;
123117 } on DetailedApiRequestError catch (e) {
124- if (e.status == 404 ) return null ;
118+ if (e.status == 404 ) {
119+ return false ;
120+ }
125121 rethrow ;
126122 }
127123 },
128- maxAttempts: 3 ,
129- retryIf: _retryIf,
130124 );
131125 }
132126
@@ -158,7 +152,7 @@ extension BucketExt on Bucket {
158152 if (maxSize != null && length != null && maxSize < length) {
159153 throw MaximumSizeExceeded (maxSize);
160154 }
161- return retry (
155+ return _retry (
162156 () async {
163157 final timeout = Duration (seconds: 30 );
164158 final deadline = clock.now ().add (timeout);
@@ -175,8 +169,6 @@ extension BucketExt on Bucket {
175169 }
176170 return builder.toBytes ();
177171 },
178- maxAttempts: 3 ,
179- retryIf: _retryIf,
180172 );
181173 }
182174
@@ -270,8 +262,17 @@ extension PageExt<T> on Page<T> {
270262 }
271263}
272264
273- Future <R > _retry <R >(Future <R > Function () fn) async {
274- return await retry (fn, maxAttempts: 3 , retryIf: _retryIf);
265+ Future <R > _retry <R >(
266+ Future <R > Function () fn, {
267+ FutureOr <void > Function (Exception )? onRetry,
268+ }) async {
269+ return await retry (
270+ fn,
271+ maxAttempts: 3 ,
272+ delayFactor: Duration (seconds: 2 ),
273+ retryIf: _retryIf,
274+ onRetry: onRetry,
275+ );
275276}
276277
277278bool _retryIf (Exception e) {
@@ -295,32 +296,6 @@ bool _retryIf(Exception e) {
295296String bucketUri (Bucket bucket, String path) =>
296297 'gs://${bucket .bucketName }/$path ' ;
297298
298- /// Deletes a single object from the [bucket] .
299- ///
300- /// Returns `true` if the object was deleted by this operation, `false` if it
301- /// didn't exist at the time of the operation.
302- Future <bool > deleteFromBucket (Bucket bucket, String objectName) async {
303- Future <bool > delete () async {
304- try {
305- await bucket.delete (objectName);
306- return true ;
307- } on DetailedApiRequestError catch (e) {
308- if (e.status != 404 ) {
309- rethrow ;
310- }
311- return false ;
312- }
313- }
314-
315- return await retry (
316- delete,
317- delayFactor: Duration (seconds: 10 ),
318- maxAttempts: 3 ,
319- retryIf: (e) =>
320- e is DetailedApiRequestError && _retryStatusCodes.contains (e.status),
321- );
322- }
323-
324299Future <void > updateContentDispositionToAttachment (
325300 ObjectInfo info, Bucket bucket) async {
326301 if (info.metadata.contentDisposition != 'attachment' ) {
@@ -351,23 +326,19 @@ Future<int> deleteBucketFolderRecursively(
351326 var count = 0 ;
352327 Page <BucketEntry >? page;
353328 while (page == null || ! page.isLast) {
354- page = await retry (
329+ page = await _retry (
355330 () async {
356331 return page == null
357332 ? await bucket.pageWithRetry (
358333 prefix: folder, delimiter: '' , pageSize: 100 )
359334 : await page.nextWithRetry (pageSize: 100 );
360335 },
361- delayFactor: Duration (seconds: 10 ),
362- maxAttempts: 3 ,
363- retryIf: (e) =>
364- e is DetailedApiRequestError && _retryStatusCodes.contains (e.status),
365336 );
366337 final futures = < Future > [];
367338 final pool = Pool (concurrency ?? 1 );
368339 for (final entry in page! .items) {
369340 final f = pool.withResource (() async {
370- final deleted = await deleteFromBucket ( bucket, entry.name);
341+ final deleted = await bucket. tryDeleteWithRetry ( entry.name);
371342 if (deleted) count++ ;
372343 });
373344 futures.add (f);
@@ -382,7 +353,7 @@ Future<int> deleteBucketFolderRecursively(
382353Future uploadWithRetry (Bucket bucket, String objectName, int length,
383354 Stream <List <int >> Function () openStream,
384355 {ObjectMetadata ? metadata}) async {
385- await retryAsync (
356+ await _retry (
386357 () async {
387358 final sink = bucket.write (objectName,
388359 length: length,
@@ -391,9 +362,9 @@ Future uploadWithRetry(Bucket bucket, String objectName, int length,
391362 await sink.addStream (openStream ());
392363 await sink.close ();
393364 },
394- description : 'Upload to $ objectName ' ,
395- shouldRetryOnError : _retryIf,
396- sleep : Duration (seconds : 10 ) ,
365+ onRetry : (e) {
366+ _logger. info ( 'Upload to $ objectName failed.' , e, StackTrace .current);
367+ } ,
397368 );
398369}
399370
@@ -506,7 +477,7 @@ class VersionedJsonStorage {
506477 final age = clock.now ().difference (info.updated);
507478 if (minAgeThreshold == null || age > minAgeThreshold) {
508479 deleted++ ;
509- await deleteFromBucket ( _bucket, entry.name);
480+ await _bucket. tryDeleteWithRetry ( entry.name);
510481 }
511482 }
512483 });
0 commit comments