test(db2-ephemeral): gates opt into WO_EPHEMERAL=1 where a durable table is declared; residency section 7

- residency-accept.sh section 7, six checks: the refusal names the class
  and all three ways forward (exit 2); WO_EPHEMERAL=1 runs from RAM with
  the boot notice and a write round-trips; WO_EPHEMERAL with WO_DATA
  refuses; WO_EPHEMERAL=2 refuses naming the accepted value; keys-resident
  still refuses under the hatch; a plain class (the corpus `methods`
  fixture) runs with no WO_DATA, rc 0, nothing on stderr
- blast radius measured gate by gate — each run without the export first,
  kept only where the program refused: oop-e2e (fixtures declare tables);
  db-bench.py's ram/msgrate/growth/randread legs (the durable legs drop it,
  so a WO_DATA in the caller's shell now refuses loudly instead of silently
  turning a RAM leg durable); db-actor per run (its restart pair sets
  WO_DATA); chat (porch's store declares RateLimitCounter default-durable —
  a library's table binds the consumer); wmux client legs (same image as
  the server, no WO_DATA; servers and the WO_DATA-carrying r11cli `env -u`)
- byte-exact compares (db-actor single-shard, wmux client) drop the one
  notice line; fibers, subprocess, log-watcher declare no table — untouched
- db-bench.py ceiling note: the checked refusal is databasev2 5's now
- residency 32/0, oop-e2e 131/0 with this tree

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
(cherry picked from commit 4553ca15da235c155b7ad31bbb077c3ad8e88fee)
This commit is contained in:
shoney.arickathil 2026-09-15 01:03:49 +02:00
parent d38b4f864b
commit 41f48bba3f
5 changed files with 82 additions and 12 deletions

View file

@ -7,6 +7,10 @@
# drain (close frames, exit 0) — functional legs on BOTH WO_IO backends
# plus an ASan run.
set -uo pipefail
# databasev2 2 (6a): chat `use`s porch, whose store middleware declares its
# tables default-durable (`RateLimitCounter`, ...) — a library-owned durable
# table binds every consumer, so this RAM-only gate opts in.
export WO_EPHEMERAL=1
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
WOC="$ROOT/compiler/_build/default/bin/woc"

View file

@ -25,10 +25,13 @@ else
bad "build" "woc failed"; echo "db-actor-accept: 1 checks, 1 failures"; exit 1
fi
# databasev2 2 (6a): these RAM-only runs opt in with WO_EPHEMERAL=1 (a durable
# table refuses to start without WO_DATA); the restart pair below sets WO_DATA
# instead, and the two are incompatible, so the hatch is per-run, not exported.
check_set() { # name [env pairs...]
local name="$1"; shift
local out
out="$(env "$@" timeout 30 "$DIR/target/db-actor" 2>&1)"
out="$(env WO_EPHEMERAL=1 "$@" timeout 30 "$DIR/target/db-actor" 2>&1)"
if printf '%s' "$out" | grep -q "writer 1 sees sum" \
&& printf '%s' "$out" | grep -q "writer 2 sees sum" \
&& printf '%s' "$out" | grep -q "^main sees 2 rows, sum 3$" ; then
@ -47,7 +50,8 @@ check_set "multi uring" WO_IO=uring
check_set "multi epoll" WO_IO=epoll
# single-shard: byte-exact — the local path is untouched
sout="$(WO_SHARDS=1 timeout 30 "$DIR/target/db-actor" 2>&1)"
# byte-exact on merged stdout+stderr, so the hatch's one boot notice is dropped
sout="$(WO_EPHEMERAL=1 WO_SHARDS=1 timeout 30 "$DIR/target/db-actor" 2>&1 | grep -v '^wovm: WO_EPHEMERAL=1')"
want=$'writer 1 sees sum 1\nwriter 2 sees sum 3\nmain sees 2 rows, sum 3'
if [[ "$sout" == "$want" ]]; then
ok "single-shard byte-exact"

View file

@ -19,9 +19,13 @@ ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
BIN = os.path.join(ROOT, "docs/examples/db-bench/target/db-bench")
# databasev2 2 task 7. Its own program, not a mode in db-bench: declaring a
# `resident: keys` table is a WHOLE-PROGRAM constraint — the runtime refuses to
# start without WO_DATA, for every mode in the module. Putting those classes in
# db-bench's shared types made growth/ceiling/randread, which deliberately run
# WITHOUT WO_DATA, refuse to start.
# start without WO_DATA, for every mode in the module, and WO_EPHEMERAL=1 does
# not rescue it. Putting those classes in db-bench's shared types made the ram,
# msgrate, growth and randread legs, which deliberately run WITHOUT WO_DATA
# (ceiling sets one — it measures what survives the kill), refuse to start.
# databasev2 2 task 6a: those RAM legs now opt in with WO_EPHEMERAL=1; a
# WO_DATA exported in the caller's shell no longer silently turns them durable,
# it refuses loudly (WO_EPHEMERAL is incompatible with WO_DATA).
RESID_BIN = os.path.join(ROOT, "docs/examples/residency-bench/target/residency-bench")
WOC = os.path.join(ROOT, "compiler/_build/default/bin/woc")
WOVM = os.path.join(ROOT, "runtime/wovm")
@ -188,12 +192,13 @@ def campaign():
for flavor in ("ram", "durable"):
for shards in (1, ncores):
tag = f"{flavor}.s{'1' if shards == 1 else 'N'}"
env = {"WO_SHARDS": str(shards)}
env = {"WO_SHARDS": str(shards), "WO_EPHEMERAL": "1"}
data = None
if flavor == "durable":
data = os.path.join(ROOT, "bench", f"tmp.{os.getpid()}.{tag}")
os.makedirs(data, exist_ok=True)
env["WO_DATA"] = data
del env["WO_EPHEMERAL"]
rc, lines, rssg, fdg = run(["all", str(N)], env, 1800, sample_after="write ")
if rc != 0:
bad(f"{tag}.all", f"rc={rc} tail={lines[-2:]}")
@ -221,7 +226,8 @@ def campaign():
# raises the cap to the flood size — the measured number keeps
# iteration 22's semantics exactly.
rc, lines, _, _ = run(["msgrate", str(MSG_N)],
{"WO_SHARDS": str(shards), "WO_MAILBOX": str(MSG_N)}, 300)
{"WO_SHARDS": str(shards), "WO_MAILBOX": str(MSG_N),
"WO_EPHEMERAL": "1"}, 300)
if rc != 0:
bad(tag, f"rc={rc}")
else:
@ -505,7 +511,7 @@ def growth(metrics):
for shape in GROWTH_SHAPES:
for legname, swap_mb in (("noswap", 0), ("swap", 256)):
w = cap_wrapper(512, swap_mb)
env = dict(os.environ)
env = dict(os.environ); env["WO_EPHEMERAL"] = "1"
argv = w + [BIN, "growth", str(GROWTH_N), shape]
pr = subprocess.run(argv, stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
text=True, env=env, timeout=900)
@ -554,9 +560,9 @@ def ceiling(metrics):
malloc succeeds and the process dies TOUCHING the pages, so it never
gets the chance to report failure. (The VM object arena is the
opposite: WO_HEAP_MB is checked and traps.) rc is asserted, not
recorded as a metric -- when databasev2 2's byte budget lands this
should become a checked refusal, and the gate must not fail on that
improvement.
recorded as a metric -- when databasev2 5's byte budget (bounded
tables) lands this should become a checked refusal, and the gate must
not fail on that improvement.
2. WHAT SURVIVES. With WO_DATA set, replay must yield a contiguous
intact prefix: rows 1..M present with the right v, no holes, and not
@ -772,7 +778,8 @@ def randread(metrics):
w = cap_wrapper(cap_mb, swap_mb)
pr = subprocess.run(w + [BIN, "randread", str(RAND_N), str(RAND_R)],
stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
text=True, env=dict(os.environ), timeout=900)
text=True, env=dict(os.environ, WO_EPHEMERAL="1"),
timeout=900)
lines = pr.stdout.splitlines()
ops, p50, p99, hits, filled = parse_randread(lines)
key = f"randread.{legname}"

View file

@ -31,6 +31,9 @@ set -uo pipefail
# narrows determinism to output SETS there); the multi-shard/TSan proofs
# live in the fibers gate, not here.
export WO_SHARDS=1 # no -e: a failing fixture is handled explicitly, one at a time
# databasev2 2 (6a): a program with any durable table (the default) refuses to
# start without WO_DATA; the corpus is RAM-only by contract, so opt in here.
export WO_EPHEMERAL=1
shopt -s nullglob
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"

View file

@ -199,6 +199,58 @@ else
bad "resident:keys refusal fixture compiles" "$(head -1 "$WORK/e")"
fi
# ---- 7. a durable table (the default) refuses to run without WO_DATA -------
# databasev2 2 task 6a: before this, a durable class with no WO_DATA ran
# RAM-only and every write was silently discarded — the exact outcome
# `durable: true` promises against. WO_EPHEMERAL=1 is the explicit opt-in to
# that RAM-only run; anything else refuses at startup, exit 2, naming the
# class and all three ways forward.
printf '@table(name: "notes", index: [k])\nclass Notes { k: Text }\nfn main() -> Int { insert Notes { k: "a" }; let n = 0; for x in from r in Notes select r { n = n + 1; } print("notes=${n}"); return 0; }\n' > "$WORK/dur.wo"
if "$WOC" --emit "$WORK/dur.wo" -o "$WORK/dur.wob" 2>"$WORK/e"; then
# (i) default-durable, no WO_DATA, no WO_EPHEMERAL -> refuse
out="$(env -u WO_DATA -u WO_EPHEMERAL "$WOVM" "$WORK/dur.wob" 2>&1)"; rc=$?
[[ $rc -eq 2 ]] && grep -q 'Notes' <<<"$out" && grep -q 'WO_DATA=' <<<"$out" \
&& grep -q 'WO_EPHEMERAL=1' <<<"$out" && grep -q 'durable: false' <<<"$out" \
&& ok "durable table without WO_DATA exits 2, names the class and all three ways forward" \
|| bad "durable table without WO_DATA refuses" "exit=$rc got: $out"
# (ii) WO_EPHEMERAL=1 -> runs from RAM: boot notice on stderr, a write round-trips
out="$(env -u WO_DATA WO_EPHEMERAL=1 "$WOVM" "$WORK/dur.wob" 2>&1)"; rc=$?
[[ $rc -eq 0 ]] && grep -q 'WO_EPHEMERAL=1' <<<"$out" && grep -q 'notes=1' <<<"$out" \
&& ok "WO_EPHEMERAL=1 runs the durable table from RAM (boot notice, write round-trips)" \
|| bad "WO_EPHEMERAL=1 runs from RAM" "exit=$rc got: $out"
# (iii) WO_EPHEMERAL together with WO_DATA -> conflict, refuse
mkdir -p "$WORK/d7"
out="$(WO_DATA="$WORK/d7" WO_EPHEMERAL=1 "$WOVM" "$WORK/dur.wob" 2>&1)"; rc=$?
[[ $rc -eq 2 ]] && grep -q 'incompatible with WO_DATA' <<<"$out" \
&& ok "WO_EPHEMERAL=1 with WO_DATA set exits 2 and names the conflict" \
|| bad "WO_EPHEMERAL + WO_DATA conflict" "exit=$rc got: $out"
# (v) the only accepted value is 1
out="$(env -u WO_DATA WO_EPHEMERAL=2 "$WOVM" "$WORK/dur.wob" 2>&1)"; rc=$?
[[ $rc -eq 2 ]] && grep -q 'WO_EPHEMERAL=1' <<<"$out" \
&& ok "WO_EPHEMERAL=2 exits 2 and names the accepted value" \
|| bad "WO_EPHEMERAL=2 refused" "exit=$rc got: $out"
else
bad "durable refusal fixture compiles" "$(head -1 "$WORK/e")"
fi
# (iv) resident:keys still refuses under WO_EPHEMERAL=1 — the keys loop wins
if [[ -f "$WORK/reskeys.wob" ]]; then
out="$(env -u WO_DATA WO_EPHEMERAL=1 "$WOVM" "$WORK/reskeys.wob" 2>&1)"; rc=$?
[[ $rc -eq 2 ]] && grep -q 'resident: keys' <<<"$out" \
&& ok "WO_EPHEMERAL=1 does not rescue resident:keys (exit 2, keys message)" \
|| bad "WO_EPHEMERAL=1 vs resident:keys" "exit=$rc got: $out"
fi
# (vi) a class that is NOT a @table is not a durable table: no WO_DATA, no
# WO_EPHEMERAL, rc 0 and nothing on stderr. `durable: true` is a @table
# property; the .wob carries the table bit (v8) so the refusal loops can tell.
if "$WOC" --emit tests/corpus/run/methods/fixture.wo -o "$WORK/plain.wob" 2>"$WORK/e"; then
out="$(env -u WO_DATA -u WO_EPHEMERAL "$WOVM" "$WORK/plain.wob" 2>"$WORK/plain.err")"; rc=$?
[[ $rc -eq 0 && "$out" == $'15\n42' ]] && ! grep -q '^wovm:' "$WORK/plain.err" \
&& ok "a plain class (no @table) runs without WO_DATA: rc 0, no wovm: line" \
|| bad "plain class without WO_DATA" "exit=$rc out: $out err: $(cat "$WORK/plain.err")"
else
bad "plain-class fixture compiles" "$(head -1 "$WORK/e")"
fi
# ---- 8. WO_DATA=<file>: the store as one file ------------------------------
# databasev2 7: WO_DATA names either a directory (-> <dir>/shard-0.wal, as it
# always did) or THE log file. Underneath it is the same wo_wal_* path, so