Skip to content

Transactions — atomic { … }

Tenant-scoped interactive transactions. Snapshot isolation at block entry; first-committer-wins on the write-set at commit.

Shape

eel
atomic {
  listings |> filter id == ${lid} && stock > 0 |> update { stock: stock - 1 }
  orders   |> insert { listing: ${lid}, buyer_ref: ${bref}, total: 129.00$, placed_at: now(), status: .pending }
}

All pipelines in the block share one snapshot pin and one commit (or abort). Cross-tenant coordination stays app-layer sagas — atomics never span tenants.

Semantics

RuleBehavior
Snapshot pinAt begin, copy the version vector. Reads resolve against the pin, not the live head.
Read-your-own-writesReads also see this block's uncommitted dirty pages (live version > pin).
Buffered writesMutations append WAL Write frames under the txn id; pages stay dirty until commit.
CommitConflict check → one Commit frame → wal.sync → flush dirty pages → Meta. Same fsync path as batch commit.
AbortDiscard dirty pages; restore last durable heads (concurrent commits stay visible). WAL Abort for recovery.
ConflictIf any key this block wrote was committed by another block after this pin → typed conflict (conflict: true on HTTP).

Crash recovery

Crash pointOn reopen
After Begin + Writes, before CommitOpen txn discarded — zero effect from the block
After Commit + WAL fsyncReplay applies all Writes; full txn visible

Scope today

  • In: single-process first-committer-wins (in-memory commit log keyed by DB path).
  • Out (later): cross-process / after-reopen conflict detection; cross-tenant atomics.

Stress and recovery harness coverage lives under Maintainers → Testing.

Pre-alpha. Local-first. Stdlib-only Rust engine. Tenant concerns shifted left into the database.