Package-level declarations

Types

Link copied to clipboard

A SyncTelemetrySink that discards every event. Default when telemetry isn't wired up.

Link copied to clipboard

Implemented by local entities/rows that participate in delta sync.

Link copied to clipboard
@Serializable
data class SyncAppliedRecord(val key: String, val id: Int? = null, val status: String, val updatedAt: Long? = null, val reason: String? = null)

One row's outcome from the server for a pushed upsert/delete.

Link copied to clipboard
data class SyncCursorRecord(val resourceName: String, val cursor: String? = null, val lastSyncedAt: Long? = null, val fullResyncRequired: Boolean = false, val metadataExtra: Map<String, String> = emptyMap())

One resource's persisted cursor/quota bookkeeping.

Link copied to clipboard
interface SyncCursorStore

Cursor/quota bookkeeping persisted per resource, keyed by SyncResourceAdapter.resourceName.

Link copied to clipboard
class SyncEngine(cursorStore: SyncCursorStore, telemetry: SyncTelemetrySink = NoOpSyncTelemetrySink)

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.

Link copied to clipboard
@Serializable
data class SyncRequest<Upsert, Delete>(val since: String? = null, val limit: Int = SyncEngine.DEFAULT_LIMIT, val upserts: List<Upsert> = emptyList(), val deletes: List<Delete> = emptyList())

Wire request envelope for one sync pass against a single resource.

Link copied to clipboard

Resource-specific glue for the generic loop in SyncEngine. Implement one of these (plus the wire DTO mapping) to make a new resource syncable — the contract logic (ack guard, pending guard, full-snapshot reconciliation, pagination drain, fullResyncRequired) lives in the engine, not here, so it holds identically for every resource.

Link copied to clipboard
@Serializable
data class SyncResponse<Change>(val syncVersion: Int, val mode: String, val applied: List<SyncAppliedRecord> = emptyList(), val serverChanges: List<Change> = emptyList(), val cursor: String? = null, val hasMore: Boolean = false, val fullResyncRequired: Boolean = false, val metadataExtra: Map<String, String> = emptyMap())

Wire response envelope for one sync pass against a single resource.

Link copied to clipboard
object SyncState

The set of local sync states a SyncableEntity row can be in.

Link copied to clipboard

Optional telemetry hook for SyncEngine. All methods are no-ops by default (NoOpSyncTelemetrySink) so wiring analytics is opt-in; bridge this to your own analytics client (e.g. the analytics-core module's AnalyticsClient) to get the same event vocabulary Novalingo's user_sync_* events used.