drain method

Future<int> drain({
  1. int batchSize = 50,
})

Best-effort: drain pending events into Supabase. Re-entrant guard via _draining so an online tick that fires while a previous drain is still in flight is a no-op. Returns the number of events that successfully replayed.

Implementation

Future<int> drain({int batchSize = 50}) async {
  if (!_outbox.isReady) return 0;
  if (_draining) return 0;
  _draining = true;
  try {
    final events = _outbox.pendingAndFailed(limit: batchSize);
    if (events.isEmpty) return 0;

    var succeeded = 0;
    for (final ev in events) {
      if (!_knownReplayTables.contains(ev.tableName)) {
        // Unknown table — leave pending so a future SyncWorker version
        // with a handler can pick it up. Don't mark failed; the row
        // isn't broken, just unsupported.
        continue;
      }
      _outbox.markSyncing(ev.id);
      try {
        await _replay(ev);
        _outbox.markSynced(ev.id);
        succeeded++;
      } catch (e) {
        _outbox.markFailed(ev.id, e.toString());
        dev.log(
          'Replay failed for ${ev.tableName}#${ev.id}: $e',
          name: 'SyncWorker',
        );
      }
    }
    if (succeeded > 0) {
      dev.log('Drained $succeeded events.', name: 'SyncWorker');
    }
    return succeeded;
  } finally {
    _draining = false;
  }
}