L1Integrity: the ten-minute re-reading runs beside the witness, not in it
On the production node a reading of the scroll takes about three seconds (3310 ms at first start; 0.9 s on the build host). The periodic re-reading ran inside the GenServer, so once every ten minutes every cycle and every readiness probe that asked "is L1 intact?" would have waited those seconds behind it. The periodic reading is now done by a task that reports back; the process goes on answering from its last reading meanwhile. The first reading is still made in the process itself — nobody is answered before the scroll has been read once — and an explicit recheck/0 is still synchronous. The next reading is scheduled when one begins, not when it reports, so a reading that dies silently is not the last. Two tests: it re-reads on its own in both directions (altered → fail, restored → tov), and a status call during a periodic reading returns at once. 484 tests, 0 failures on seeds 0 7 42 99. Built image, run with a live-mounted scroll: l1_hash pass, /peah/ask 200; then אחד in Devarim 6:4 was changed to אחר while the vessel ran and the witness asked to read again — L1_INTEGRITY_FAILED, l1_hash fail, /peah/ask 503. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
1 parent
bbe2c4b7ba
commit
ec8cdc840b
2 files changed
+48
-5
No files matched your search
@@ -126,6 +126,27 @@ defmodule VavPipeline.Tablet38L1IntegrityTest do
|
||||
File.write!(Path.join([root, "torah", "index.json"]), "INDEX, altered")
|
||||
|
||||
assert eventually(fn -> match?({:error, _}, L1Integrity.status(:tablet38_periodic)) end)
|
||||
|
||||
# And it keeps re-reading: restored, it is tov again without being asked.
|
||||
File.write!(Path.join([root, "torah", "index.json"]), "INDEX")
|
||||
assert eventually(fn -> L1Integrity.status(:tablet38_periodic) == :ok end)
|
||||
end
|
||||
|
||||
test "answers from the last reading while a periodic re-reading is under way" do
|
||||
root = small_scroll()
|
||||
{:ok, pinned} = L1Reader.compute_tree_hash(root)
|
||||
|
||||
{:ok, pid} =
|
||||
L1Integrity.start_link(name: :tablet38_busy, l1_root: root, expected_hash: pinned, interval: :never)
|
||||
|
||||
on_exit(fn -> if Process.alive?(pid), do: GenServer.stop(pid) end)
|
||||
|
||||
# Trigger a periodic reading by hand; the process must not be busy
|
||||
# with it — a status call is answered at once, from the last reading.
|
||||
send(pid, :read)
|
||||
{micros, status} = :timer.tc(fn -> L1Integrity.status(:tablet38_busy) end)
|
||||
assert status == :ok
|
||||
assert micros < 50_000
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
Reference in new issue
Block a user