OfflineOutboxService class
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.
Lifecycle: an item is enqueued → sits pending → drain calls uploader for it → either SyncAck (item removed) or SyncConflict (handled per conflictPolicy, see there) → a ConflictPolicy.manual or unresolved ConflictPolicy.merge conflict parks it in manualReviewItems until resolveManual.
Crash safety: an item stays in the persisted outbox from enqueue until the exact call that removes it also persists that removal — so a crash at any point before that (including between the remote authority accepting it and this service recording that) leaves the item still queued for the next drain, which retries it with the same OutboxItem.idempotencyKey. Nothing is ever lost; avoiding a duplicate effect on the remote side is the injected uploader's responsibility (a real backend keys on OutboxItem.idempotencyKey to dedupe a retried request it already applied) — this service only guarantees it always retries safely, never that it never retries.
Error handling: every public method returns SdkResult — this service never throws for a caller-facing error.
Compatibility: storageKey namespaces the persisted JSON blob the
same way every other kit service's storageKey does — pass a distinct
one per independent outbox instance (e.g. one per save slot).
- Inheritance
-
- Object
- GetLifeCycle
- DisposableInterface
- GetxService
- OfflineOutboxService
Constructors
- OfflineOutboxService({required StorageService storage, required OutboxUploader uploader, ConnectivityCoordinator? connectivity, ConflictPolicy conflictPolicy = ConflictPolicy.manual, ConflictMerger? merger, int capacity = 200, RetryPolicy retryPolicy = const RetryPolicy(maxAttempts: 3), RetryExecutor? retryExecutor, String? storageKey})
Properties
- capacity → int
-
final
- conflictPolicy → ConflictPolicy
-
final
- connectivity → ConnectivityCoordinator?
-
final
- hashCode → int
-
The hash code for this object.
no setterinherited
- initialized → bool
-
Checks whether the controller has already been initialized.
no setterinherited
- isClosed → bool
-
Checks whether the controller has already been closed.
no setterinherited
-
items
→ RxList<
OutboxItem> -
final
-
manualReviewItems
→ List<
OutboxItem> -
no setter
- merger → ConflictMerger?
-
final
-
onDelete
→ InternalFinalCallback<
void> -
Internal callback that starts the cycle of this controller.
finalinherited
-
onStart
→ InternalFinalCallback<
void> -
Called at the exact moment the widget is allocated in memory.
It uses an internal "callable" type, to avoid any @overrides in subclases.
This method should be internal and is required to define the
lifetime cycle of the subclass.
finalinherited
- retryPolicy → RetryPolicy
-
final
- runtimeType → Type
-
A representation of the runtime type of the object.
no setterinherited
- storage → StorageService
-
final
- uploader → OutboxUploader
-
final
Methods
-
$configureLifeCycle(
) → void -
inherited
-
drain(
) → Future< void> - Attempts to sync every non-OutboxItem.manualReview item, highest-OutboxItem.priority first. Safe to call concurrently with itself (a no-op re-entry) or with enqueue/resolveManual.
-
enqueue(
{required String idempotencyKey, required Map< String, Object?> payload, int priority = 0, int? expiresAtMs}) → SdkResult<void> -
Queues
payloadunderidempotencyKey— replaces any existing item with the same key rather than duplicating it. Bounded at capacity: once full, the lowest-priorityitem is evicted to make room. -
noSuchMethod(
Invocation invocation) → dynamic -
Invoked when a nonexistent method or property is accessed.
inherited
-
onClose(
) → void -
Called before onDelete method. onClose might be used to
dispose resources used by the controller. Like closing events,
or streams before the controller is destroyed.
Or dispose objects that can potentially create some memory leaks,
like TextEditingControllers, AnimationControllers.
Might be useful as well to persist some data on disk.
override
-
onInit(
) → void -
Called immediately after the widget is allocated in memory.
You might use this to initialize something for the controller.
override
-
onReady(
) → void -
Called 1 frame after onInit(). It is the perfect place to enter
navigation events, like snackbar, dialogs, or a new route, or
async request.
inherited
-
resolveManual(
{required String idempotencyKey, required ManualResolution resolution}) → SdkResult< void> - Resolves an item sitting in manualReviewItems. ManualResolution.keepLocal re-queues its original payload for another drain attempt; ManualResolution.acceptRemote removes it — the local change is abandoned, nothing further is attempted.
-
toString(
) → String -
A string representation of this object.
inherited
Operators
-
operator ==(
Object other) → bool -
The equality operator.
inherited
Static Properties
- maybe → OfflineOutboxService?
-
no setter