SyncEngine

class SyncEngine(cursorStore: SyncCursorStore, telemetry: SyncTelemetrySink = NoOpSyncTelemetrySink, clockMs: () -> Long = System::currentTimeMillis)

Drives offline, cross-device delta sync for user-owned resources through one generic loop. Resources plug in as SyncResourceAdapters; this engine owns the contract invariants (ack guard, pending guard, full-snapshot tombstone reconciliation, pagination drain, fullResyncRequired), so they hold identically for all resources and a new resource cannot accidentally skip one.

This is a plain, DI-framework-agnostic class: construct it with your own SyncCursorStore and (optionally) a SyncTelemetrySink, and wire it into whatever DI container your app uses.

Coroutine cancellation is never converted into a failed Result: cancelling the caller cancels the pass and rethrows CancellationException, and is not reported as a sync failure.

Parameters

clockMs

wall-clock source for lastSyncedAt and telemetry durations; override in tests.

Constructors

Link copied to clipboard
constructor(cursorStore: SyncCursorStore, telemetry: SyncTelemetrySink = NoOpSyncTelemetrySink, clockMs: () -> Long = System::currentTimeMillis)

Types

Link copied to clipboard
object Companion

Functions

Link copied to clipboard
suspend fun <E : SyncableEntity<E>, U, D, C> sync(adapter: SyncResourceAdapter<E, U, D, C>, limit: Int = DEFAULT_LIMIT): Result<Unit>

Runs a single resource's sync pass with one unbounded push and response pages of limit rows.

suspend fun <E : SyncableEntity<E>, U, D, C> sync(adapter: SyncResourceAdapter<E, U, D, C>, limit: Int = DEFAULT_LIMIT, pushBatchSize: Int): Result<Unit>

Runs a resource with at most pushBatchSize pending rows per request, counting upserts and deletes together. limit still controls response page size and is sent unchanged.

Link copied to clipboard
suspend fun syncAll(adapters: List<SyncResourceAdapter<*, *, *, *>>, limit: Int = DEFAULT_LIMIT): Result<Unit>

Runs adapters in sequence under one sync pass. Per-resource isolation: one resource failing does not abort the others; the first failure (if any) is returned once all adapters have been attempted, with later failures attached via Throwable.addSuppressed.

suspend fun syncAll(adapters: List<SyncResourceAdapter<*, *, *, *>>, limit: Int = DEFAULT_LIMIT, pushBatchSize: Int): Result<Unit>

Runs all resources with opt-in bounded pushes. See sync for the server requirements and the distinction between limit and pushBatchSize. Failures remain isolated per resource.