core/offline_outbox_service library
Classes
- OfflineOutboxService
- Persisted, priority-drained outbox for syncing local changes to a remote authority once back online — built on RetryExecutor (FEAT-35) for transient-failure backoff and, when connectivity is supplied, driven automatically by ConnectivityCoordinator (FEAT-62)'s online transitions the same way that service drains its own internal task queue.
- OutboxItem
-
One queued, not-yet-synced unit of work. payload is plain,
caller-defined JSON data — same "never put a secret in it, it's
persisted locally in plain JSON" caveat as
RewardTransactionRecord.receiptMeta(FEAT-42). - SyncAck
- The remote authority accepted the payload as-is.
- SyncConflict
- The remote authority's state for this OutboxItem.idempotencyKey has diverged from what was queued — remotePayload is its current value, handled per ConflictPolicy.
- SyncOutcome
- Result of one OutboxUploader call.
Enums
- ConflictPolicy
- What to do when OfflineOutboxService uploads an item and the remote authority reports its state has diverged from what was queued locally.
- ManualResolution
- What a caller decided for an item sitting in OfflineOutboxService.manualReviewItems.
Typedefs
-
ConflictMerger
= Map<
String, Object?> Function(Map<String, Object?> local, Map<String, Object?> remote) - A ConflictPolicy.merge resolution: given the payload that was queued locally and the authority's current payload for the same key, return the payload to re-upload. Must be pure/deterministic — same inputs, same output — since a crash between the merge and the retry may run it again.
-
OutboxUploader
= Future<
SyncOutcome> Function(Map<String, Object?> payload, String idempotencyKey) -
Attempts to sync one item with whatever remote authority a consumer app
wires up (a REST endpoint, a cloud function, ...) — this service knows
nothing about the transport. Throwing (a network error, a timeout) is
treated as transient and retried per OfflineOutboxService.retryPolicy;
returning a SyncOutcome is the only way to report a definitive
accept/conflict.
idempotencyKeyis passed on every attempt (including retries after a crash) specifically so the remote side can dedupe a request it already applied.