Skip to main content

Crate baukit_sync

Crate baukit_sync 

Source
Expand description

Revision allocation, tombstone purge horizons, and hybrid logical clocks for incremental sync.

A syncable row carries a revision drawn from a counter that is private to its owner. A client pulls by asking for everything above the revision it last saw, so the counter must be monotonic per owner and must move in the same transaction as the row write it stamps. [next_revision] does exactly that. The [purge] module deletes old tombstones and records the per-owner purge horizon, and horizon holds the pull-cursor rule that turns a cursor below the horizon into a full-resync signal. The hlc module supplies a cross-runtime logical clock for ordering writes when physical clocks stall or move backward.

§Features

Without features the crate contains only hlc, horizon, and the reference SQL constants, and depends on no database driver. The sqlx-postgres feature adds the PostgreSQL revision allocator and the [purge] module.

§What this crate is not

Baukit does not standardize a sync protocol. Wire payloads, conflict resolution, batching, and the pull endpoint stay product-owned, as docs/platform/offline-readiness-contract.md says. This crate owns revision allocation, tombstone purge horizons, and timestamp generation. Merge rules, retention periods, table lists, and scheduling stay product-owned.

§Schema

Products copy POSTGRES_MIGRATION_SQL and POSTGRES_PURGE_HORIZONS_MIGRATION_SQL into their own ordered migrations; the crate never runs migrations at process startup. Products whose existing counter uses user_id can instead copy POSTGRES_RENAME_USER_ID_TO_OWNER_ID_SQL. The reference migration also documents the column convention every syncable table follows: id, owner_id, updated_at, deleted_at, revision, plus an (owner_id, revision) index.

§Usage

Call [next_revision] inside the transaction that writes the row, and stamp the returned value onto that row. If the transaction rolls back, the allocation rolls back with it and the revision is never handed out.

let mut transaction = pool.begin().await?;
let revision = baukit_sync::next_revision(&mut transaction, owner_id).await?;
sqlx::query("UPDATE product_records SET revision = $1 WHERE owner_id = $2")
    .bind(revision)
    .bind(owner_id)
    .execute(&mut *transaction)
    .await?;
transaction.commit().await?;

Modules§

hlc
Hybrid logical timestamps compatible with JavaScript safe integers.
horizon
Pull-cursor rules for tombstone purge horizons.

Constants§

POSTGRES_MIGRATION_SQL
Reference PostgreSQL schema and column convention for product migrations.
POSTGRES_PURGE_HORIZONS_MIGRATION_SQL
Reference PostgreSQL schema for per-owner tombstone purge horizons.
POSTGRES_RENAME_USER_ID_TO_OWNER_ID_SQL
One-shot PostgreSQL migration from sync_revisions.user_id to owner_id.