flush method

Future<void> flush(
  1. Future<void> dispatcher(
    1. OutboxMutation mutation
    ), {
  2. void onMutationError(
    1. OutboxMutation mutation,
    2. Object error
    )?,
  3. bool ignoreBackoff = false,
  4. Duration baseBackoff = const Duration(milliseconds: 100),
  5. Duration maxBackoff = const Duration(seconds: 60),
})

Dispatches all pending mutations for the active tenant via dispatcher.

Mutations belonging to inactive (signed-out) tenants are left in the queue — they will be dispatched when their tenant is next set active.

Concurrent callers share the active pass; enqueues during a pass wait for the next flush. Bind the dispatcher to immutable tenant credentials before calling this method. Already sent requests cannot be recalled on sign-out. Error-observer exceptions are reported after queue bookkeeping completes.

Individual mutation errors do not abort the entire flush pass:

  • The failed mutation increments its retry count and sets an exponential backoff OutboxMutation.nextRetryAfter timestamp, capped at maxBackoff.
  • Mutations that have not reached their backoff window are skipped.
  • If the retry threshold is reached, it is moved to the dead-letter queue.
  • Subsequent mutations continue processing to avoid head-of-line blocking.

Implementation

Future<void> flush(
  Future<void> Function(OutboxMutation mutation) dispatcher, {
  void Function(OutboxMutation mutation, Object error)? onMutationError,
  bool ignoreBackoff = false,
  Duration baseBackoff = const Duration(milliseconds: 100),
  Duration maxBackoff = const Duration(seconds: 60),
}) {
  final running = _flushFuture;
  if (running != null) return running;
  final completion = Completer<void>();
  _flushFuture = completion.future;
  _flush(
    dispatcher,
    onMutationError: onMutationError,
    ignoreBackoff: ignoreBackoff,
    baseBackoff: baseBackoff,
    maxBackoff: maxBackoff,
  ).then(
    (_) {
      _flushFuture = null;
      completion.complete();
    },
    onError: (Object error, StackTrace stack) {
      _flushFuture = null;
      completion.completeError(error, stack);
    },
  );
  return completion.future;
}