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_idtoowner_id.