Task 4 of docs/superpowers/plans/2026-08-26-table-residency.md — the first behavioural change in the iteration. - db.c: one predicate, `table_is_durable`, gating the three EXISTING mutation sites. Kept as a function rather than an inlined condition so database/src/CODE-LOGIC.md's "nothing else may mutate storage" claim keeps holding — the choke points stayed three - the ack contract is untouched for durable tables: RAM applied, record staged, one commit before the ack, and a failed commit still removes the row - replay: a log holding records for a class the image now declares volatile is a real migration case, not corruption. apply_record returns -2 (distinct from -1), wo_wal_replay_ex reports the class id, and main.c names it and exits 2. `wo_wal_replay` stays as the NULL wrapper, so all 156 WAL unit checks are untouched - measured, not asserted: 50 inserts wrote 1500 WAL bytes into a durable table and ZERO into a volatile one. The file's SIZE proves nothing (it is fallocate'd to 1 MiB up front), so the gate measures the non-zero prefix BUG I INTRODUCED AND CAUGHT: the mismatch message first printed the class name with %s, but wo_str.data is `char data[]` with NO NUL terminator (obj.h) — a buffer over-read. Now %.*s with the explicit length, and re-verified under ASan. New gate `just residency` (8 checks), because everything above was otherwise a one-off manual measurement: restart behaviour, the zero-byte write path, the mismatch refusal (exit 2, names the class, NOT reported as corruption), and both compile-time refusals. Its own first run failed two checks for a bug in the script rather than the feature — `woc | grep` under `set -o pipefail` returns woc's exit 1 even when grep matches, since woc exits 1 whenever it reports diagnostics. Captures first now, with the reason noted inline. Also new: corpus run/table-volatile-inprocess pins that a volatile table is a FULL table in-process — same @unique enforcement, same index probe, same query surface. Only survival differs, and that is unobservable from inside one process. Gates: woc-test 557/0, 18 runtime suites 0 fail, cli_smoke OK, oop-e2e 119/0 (was 118), residency 8/0, employee 8/0, db-actor 8/0, site 21/0, ASan clean on the new replay path. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
30 lines
1,011 B
Text
30 lines
1,011 B
Text
-- databasev2 2: a `durable: false` table is a FULL table for the life of the
|
|
-- process — same indexes, same @unique enforcement, same FK restrict, same
|
|
-- query surface. Only its survival differs, and that cannot be observed from
|
|
-- inside one process, so this fixture pins the in-process half. The restart
|
|
-- half is scripts/residency-accept.sh.
|
|
|
|
@table(name: "sessions", durable: false, index: [who])
|
|
class Session {
|
|
token: Text @unique
|
|
who: Text
|
|
}
|
|
|
|
fn main() -> Int {
|
|
insert Session { token: "t1", who: "asha" };
|
|
insert Session { token: "t2", who: "asha" };
|
|
|
|
let n = 0;
|
|
for s in from x in Session select x { n = n + 1; }
|
|
print("rows ${n}");
|
|
|
|
-- @unique still bites on a volatile table
|
|
let dup = try insert Session { token: "t1", who: "eve" } catch (e) nil;
|
|
if dup == nil { print("unique refused"); }
|
|
|
|
-- the index-backed probe still works
|
|
for s in from x in Session where x.who == "asha" order by x.token select x {
|
|
print("who ${s.who} token ${s.token}");
|
|
}
|
|
return 0;
|
|
}
|