@@ -44,7 +44,7 @@ extension StorageExt on Storage {
4444 /// local environment.
4545 Future <void > verifyBucketExistenceAndAccess (String bucketName) async {
4646 // check bucket existence
47- if (! await bucketExists (bucketName)) {
47+ if (! await bucketExistsWithRetry (bucketName)) {
4848 final message = 'Bucket "$bucketName " does not exists!' ;
4949 _logger.shout (message);
5050 if (envConfig.isRunningLocally) {
@@ -69,10 +69,29 @@ extension StorageExt on Storage {
6969 return ;
7070 }
7171 }
72+
73+ /// Check whether a cloud storage bucket exists with the default retry.
74+ Future <bool > bucketExistsWithRetry (String bucketName) async {
75+ return await _retry (() => bucketExists (bucketName));
76+ }
77+
78+ /// Copy an object with the default retry.
79+ Future <void > copyObjectWithRetry (
80+ String src,
81+ String dest, {
82+ ObjectMetadata ? metadata,
83+ }) async {
84+ return await _retry (() async => await copyObject (src, dest));
85+ }
7286}
7387
7488/// Additional methods on buckets.
7589extension BucketExt on Bucket {
90+ /// Lookup object metadata with default retry.
91+ Future <ObjectInfo > infoWithRetry (String name) async {
92+ return await _retry (() => info (name));
93+ }
94+
7695 /// Returns an [ObjectInfo] if [name] exists, `null` otherwise.
7796 Future <ObjectInfo ?> tryInfo (String name) async {
7897 return await retry (
@@ -89,6 +108,11 @@ extension BucketExt on Bucket {
89108 );
90109 }
91110
111+ /// Delete an object with default retry.
112+ Future <void > deleteWithRetry (String name) async {
113+ return await _retry (() => delete (name));
114+ }
115+
92116 /// Deletes [name] if it exists, ignores 404 otherwise.
93117 Future <void > tryDelete (String name) async {
94118 return await retry (
@@ -159,6 +183,35 @@ extension BucketExt on Bucket {
159183 String objectUrl (String objectName) {
160184 return '${activeConfiguration .storageBaseUrl }/$bucketName /$objectName ' ;
161185 }
186+
187+ /// Update object metadata with default retry rules.
188+ Future <void > updateMetadataWithRetry (
189+ String objectName, ObjectMetadata metadata) async {
190+ return await _retry (() async => await updateMetadata (objectName, metadata));
191+ }
192+
193+ /// Start paging through objects in the bucket with the default retry.
194+ Future <Page <BucketEntry >> pageWithRetry (
195+ {String ? prefix, String ? delimiter, int pageSize = 50 }) async {
196+ return await _retry (
197+ () async => await page (
198+ prefix: prefix,
199+ delimiter: delimiter,
200+ pageSize: pageSize,
201+ ),
202+ );
203+ }
204+ }
205+
206+ extension PageExt <T > on Page <T > {
207+ /// Move to the next page with default retry.
208+ Future <Page <T >> nextWithRetry ({int pageSize = 50 }) async {
209+ return await _retry (() => next (pageSize: pageSize));
210+ }
211+ }
212+
213+ Future <R > _retry <R >(Future <R > Function () fn) async {
214+ return await retry (fn, maxAttempts: 3 , retryIf: _retryIf);
162215}
163216
164217bool _retryIf (Exception e) {
@@ -212,7 +265,7 @@ Future<void> updateContentDispositionToAttachment(
212265 ObjectInfo info, Bucket bucket) async {
213266 if (info.metadata.contentDisposition != 'attachment' ) {
214267 try {
215- await bucket.updateMetadata (
268+ await bucket.updateMetadataWithRetry (
216269 info.name, info.metadata.replace (contentDisposition: 'attachment' ));
217270 } on Exception catch (e, st) {
218271 _logger.warning (
0 commit comments