| // Copyright 2024 The Flutter Authors | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file or at https://developers.google.com/open-source/licenses/bsd. | |
| import 'dart:async'; | |
| /// Runs [callback] and retries if an exception is thrown. | |
| /// | |
| /// * [maxRetries] the maximum number of times [callback] will be ran before | |
| /// rethrowing an exception if it does not complete successfully. | |
| /// * [retryDelay] the time to wait between retry attempts. | |
| /// * [stopCondition] an optional callback that determines whether we should | |
| /// stop retrying, in addition to the condition that we must not retry | |
| /// more than [maxRetries] times. If the [stopCondition] is met, we will stop | |
| /// retrying without exception. | |
| /// * [onRetry] an optional callback that will be called if [callback] fails | |
| /// and we need to attempt a retry. | |
| Future<void> runWithRetry({ | |
| required FutureOr<void> Function() callback, | |
| required int maxRetries, | |
| Duration retryDelay = const Duration(milliseconds: 250), | |
| FutureOr<bool> Function()? stopCondition, | |
| FutureOr<void> Function(int attempt)? onRetry, | |
| }) async { | |
| for ( | |
| var attempt = 1; | |
| attempt <= maxRetries && (await stopCondition?.call() != true); | |
| attempt++ | |
| ) { | |
| try { | |
| await callback(); | |
| break; | |
| } catch (e) { | |
| if (attempt == maxRetries) { | |
| rethrow; | |
| } | |
| await onRetry?.call(attempt); | |
| await Future.delayed(retryDelay); | |
| } | |
| } | |
| } |