jonnify·persistence /echo-persistence/tigris+fence/the-create-if-not-exists-fence

Module 9 · Dive 9.2

The create-if-not-exists fence.

Module 3 introduced the fence as a primitive. Here it does real work: the durable commit is a create-if-not-exists on the next commit object, and because the bucket is shared, the bucket itself is the arbiter. Three different writers — the native engine, the Rust engine, a replica promoting itself — can all reach for the same slot; exactly one wins, the rest get ConditionNotMatch and step down. The commit chain stays strictly linear. Let writers race.

§1

One slot, one winner

interactive
The bucket arbitrates. Each writer knows some head and tries to create the next commit object. A writer at the true head wins (created); one on a stale head loses (ConditionNotMatch), re-reads, and retries. Have different writers attempt, in any order.
native engine knows head: 3 Rust engine knows head: 3 promoting replica knows head: 3 commit/ chain · the durable log head idle
readout · All three know head 3. Have one attempt: it creates commit/4 and wins. Now have another attempt — it’s still on head 3, so commit/4 exists and it gets ConditionNotMatch; it re-reads head 4 and can try commit/5. The chain never forks.
§2

Why the log can’t fork

graft.engine-split.design.md

A commit is durable only when its commit object exists in the bucket, and the object is written with create-if-not-exists keyed by LSN. That single rule makes forking impossible: two writers can both believe they are at the head and both try to create commit/N+1, but the object store admits exactly one create — the other comes back a conditional-write conflict — ConditionNotMatch from the Rust engine’s OpenDAL put_commit if_not_exists, the matching If-None-Match 412 from the native engine’s create-only PUT, the same rule two ways. The loser is not wedged; it re-reads the head it now knows exists, sees the winner’s commit, and retries at N+2. Crucially, none of this depends on which engine is asking: the native engine writing directly to Tigris and the Rust engine writing through OpenDAL (Dive 8.2) express the same conditional create, so the bucket arbitrates across engines and even admits a replica promoting itself to writer. The result is a strictly linear commit chain with a single owner per link — the same OCC guarantee the VolumeServer gave locally (Module 7), now enforced by the shared remote for everyone at once. With the head safe, the last question is reading it back cold.

§3

References & sources