replay method

Replays all queued mutations in FIFO order.

Each mutation is executed via its PendingMutation.replay closure, which calls the original MutationController.mutate with the original variables. State transitions (success/failure) are emitted on the controller's stream as normal.

Returns an OfflineReplayResult describing the outcome.

Implementation

Future<OfflineReplayResult> replay() async {
  if (_queue.isEmpty) {
    return const OfflineReplayResult(
      succeeded: 0,
      failed: 0,
      failedMutations: [],
      skipped: [],
    );
  }

  var succeeded = 0;
  var failed = 0;
  final failedMutations = <PendingMutation>[];
  final skipped = <PendingMutation>[];

  // Snapshot to iterate — we will re-enqueue leftovers as needed.
  final toReplay = List<PendingMutation>.from(_queue);
  _queue.clear();

  for (final mutation in toReplay) {
    if (failed > 0 && stopOnFirstError) {
      skipped.add(mutation);
      continue;
    }

    try {
      await mutation.replay();
      succeeded++;
    } catch (_) {
      failed++;
      failedMutations.add(mutation);
    }
  }

  // Re-enqueue anything that did not run so it survives the next reconnect.
  if (stopOnFirstError && failedMutations.isNotEmpty) {
    _queue.addAll(failedMutations);
  }
  if (skipped.isNotEmpty) {
    _queue.addAll(skipped);
  }

  return OfflineReplayResult(
    succeeded: succeeded,
    failed: failed,
    failedMutations: List.unmodifiable(failedMutations),
    skipped: List.unmodifiable(skipped),
  );
}