From 4e8f7e6e6648e4d147dda71ce1dd6dfa1a5f3a92 Mon Sep 17 00:00:00 2001 From: Scott MacDougall Date: Wed, 12 Aug 2020 22:06:13 -0400 Subject: [PATCH 1/2] Added retryIfValue and onRetryIfValue to support retry on returned value conditions --- retry/example/main.dart | 4 +++- retry/lib/retry.dart | 26 ++++++++++++++++++++++---- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/retry/example/main.dart b/retry/example/main.dart index f640d10f..1ee72b57 100644 --- a/retry/example/main.dart +++ b/retry/example/main.dart @@ -14,7 +14,8 @@ import 'dart:async'; import 'dart:io'; -import 'package:retry/retry.dart'; + +import '../lib/retry.dart'; Future main() async { // Create an HttpClient. @@ -34,6 +35,7 @@ Future main() async { }, // Retry on SocketException or TimeoutException retryIf: (e) => e is SocketException || e is TimeoutException, + retryIfValue: (v) => v == 500, ); // Print result from status code diff --git a/retry/lib/retry.dart b/retry/lib/retry.dart index 5e6604ed..f6dea191 100644 --- a/retry/lib/retry.dart +++ b/retry/lib/retry.dart @@ -44,6 +44,7 @@ final _rand = math.Random(); /// () => http.get('https://google.com').timeout(Duration(seconds: 5)), /// // Retry on SocketException or TimeoutException /// retryIf: (e) => e is SocketException || e is TimeoutException, +/// retryIfValue: (v) => v == 500, /// ); /// print(response.body); /// ``` @@ -110,9 +111,9 @@ class RetryOptions { } /// Call [fn] retrying so long as [retryIf] return `true` for the exception - /// thrown. + /// thrown, or if [retryIfValue] returns `true` for the value returned from [fn]. /// - /// At every retry the [onRetry] function will be called (if given). The + /// At every retry the [onRetry] and [onRetryIfValue] functions will be called (if given). The /// function [fn] will be invoked at-most [this.attempts] times. /// /// If no [retryIf] function is given this will retry any for any [Exception] @@ -122,13 +123,22 @@ class RetryOptions { FutureOr Function() fn, { FutureOr Function(Exception) retryIf, FutureOr Function(Exception) onRetry, + FutureOr Function(dynamic) retryIfValue, + FutureOr Function(dynamic) onRetryIfValue, }) async { int attempt = 0; // ignore: literal_only_boolean_expressions while (true) { attempt++; // first invocation is the first attempt try { - return await fn(); + var value = await fn(); + if (retryIfValue == null || !(await retryIfValue(value))) { + return value; + } else { + if (onRetryIfValue != null) { + await onRetryIfValue(value); + } + } } on Exception catch (e) { if (attempt >= maxAttempts || (retryIf != null && !(await retryIf(e)))) { @@ -179,10 +189,18 @@ Future retry( int maxAttempts = 8, FutureOr Function(Exception) retryIf, FutureOr Function(Exception) onRetry, + FutureOr Function(dynamic) retryIfValue, + FutureOr Function(dynamic) onRetryIfValue, }) => RetryOptions( delayFactor: delayFactor, randomizationFactor: randomizationFactor, maxDelay: maxDelay, maxAttempts: maxAttempts, - ).retry(fn, retryIf: retryIf, onRetry: onRetry); + ).retry( + fn, + retryIf: retryIf, + onRetry: onRetry, + retryIfValue: retryIfValue, + onRetryIfValue: onRetryIfValue, + ); From a2626b251f7b8d02f5f3a5582b6f1e63d208d5cc Mon Sep 17 00:00:00 2001 From: Scott MacDougall Date: Wed, 12 Aug 2020 22:20:53 -0400 Subject: [PATCH 2/2] Added retryIfValue test --- retry/example/main.dart | 2 +- retry/test/retry_test.dart | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/retry/example/main.dart b/retry/example/main.dart index 1ee72b57..2232be1d 100644 --- a/retry/example/main.dart +++ b/retry/example/main.dart @@ -15,7 +15,7 @@ import 'dart:async'; import 'dart:io'; -import '../lib/retry.dart'; +import 'package:retry/retry.dart'; Future main() async { // Create an HttpClient. diff --git a/retry/test/retry_test.dart b/retry/test/retry_test.dart index 6bfe8d62..7b9e4bdb 100644 --- a/retry/test/retry_test.dart +++ b/retry/test/retry_test.dart @@ -131,5 +131,19 @@ void main() { await expectLater(f, throwsA(isException)); expect(count, equals(2)); }); + + test('retry (retryIfValue, success after 3)', () async { + int count = 0; + final r = RetryOptions( + maxAttempts: 5, + maxDelay: Duration(), + ); + final f = r.retry(() { + count++; + return count; + }, retryIfValue: (v) => v < 3); + await expectLater(f, completion(3)); + expect(count, equals(3)); + }); }); }