offlineRetryProvider top-level property

StreamProvider<void> offlineRetryProvider
final

Implementation

final offlineRetryProvider = StreamProvider<void>((ref) async* {
  Set<OfflineOperation> _offlineOperations() {
    return internalRepositories.values
        .map((r) {
          final adapter = r.remoteAdapter;
          // if the stream is called before initialization
          // (or after disposal) simply return an empty set
          if (!adapter.isInitialized) {
            return <OfflineOperation>{};
          }
          return adapter.offlineOperations;
        })
        .expand((e) => e)
        .toSet();
  }

  final pool = Pool(4, timeout: Duration(seconds: 30));

  var _counter = 0;

  while (true) {
    // sort operations by timestamp
    final ops = _offlineOperations().toList()
      ..sort((a, b) => a.timestamp.compareTo(b.timestamp));

    if (ops.isEmpty) {
      _counter = 0;
      await Future.delayed(Duration(milliseconds: backoffFn(4)));
      continue;
    }

    print(
        '[offline] retrying ${ops.length} operations: ${ops.map((op) => op.label)}');

    try {
      final result = pool.forEach(
        ops,
        (OfflineOperation op) async => op.retry(),
      );
      await for (final _ in result) {}
    } finally {
      final duration =
          Duration(milliseconds: backoffFn(_counter) + ops.length * 50);
      print('[offline] waiting $duration to try again');
      await Future.delayed(duration);
      _counter++;
    }
  }
});