joule-moq-relay: DVR on the relay, seek back by FETCH, and the seek power (L7b) #351
Loading…
Reference in a new issue
No description provided.
Delete branch "joule-moq/dvr"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
L7b of WAI's live and interactive work: DVR on the relay. The relay keeps a configurable window of a room's tracks on disk, every object with its receipts. A viewer seeks back into it with MOQT FETCH, addressed as live-recording §8 says, and verifies recorded objects exactly as it verifies live ones.
What is in it
joule-moq-relay/src/dvr.rs):live_rooms_verify.pyand wai-rslive_room::seek_checkcover it; the relay checks it on every FETCH below the live edge.joule-moq-roomgives every role the power.WMH1version 2 adds a hop's DVR figures (bytes stored and served), with a version 2 corpus, its refusals, andlive_metering_verify.py.joule-moq-web/web/room, with its end-to-end scenario.joule-moq-ingestreads the seek power.Defects found and fixed while finishing (the builder stopped at the account's weekly limit)
local_planbuilt a run of store-evicted groups by searching the cache from the run's first group, which the cache had already declined. The run then ended atg − 1: inverted, and at group 0 a subtraction overflow that panicked the session's task. The search now starts aftergand skips cache-evicted groups. There are unit tests, shown failing under the old rule (exit 101).Found while merging main: an end-to-end encrypted room was kept
L10 (#345) merged while this PR was being finished. Its confidentiality §9 says a room with a confidentiality record is never recorded, and "a relay keeps nothing of the room's tracks beyond delivery". The DVR store kept every track its prefix rules matched, sealed rooms included. Each slice was consistent alone, and the merge was clean apart from the changelog. Fixed here:
SECURE_OBJECT_KEY_ID, confidentiality §4.3) in its properties. Properties that do not read count as sealed too.decisions.wdland writes nothing more of the room. Moderation still honours the room's decisions for what the cache delivers.sealed.wdl(room(32) check(32)), so the store keeps refusing it after a restart. Every other room keeps its window.a_sealed_room_is_never_keptruns a sealed room beside a clear room, before and after a restart. Falsified twice: with detection off it fails at the sealed-room wait, and with deletion off it fails at "… is kept" (exit 101 each).keep_late) now useDvr::stores(a rule matches and the room is not sealed).keepsstill decides which events tracks moderation reads.Checks on the build host (rb, at
c297283ff, after merging main)The head after it,
f8b199a65, rewords one sentence of live-metering §3.1. As a link, the sentence tripped the section-reference check (its[matched the table's[start, end)interval), and "keeps none signs" matched the public-text check. The verifier and both checks pass on it.Cargo.lockwithcargo metadata --locked --offlinelibwebrtcskipped, ascheck-lockfiles.shdoes)cargo test --all-targetsofjoule-moq-relayandjoule-moq-ingest;joule-moq-web;joule-moq-room(its own workspace)sealed_objectsrelay tests among themcargo clippyof the relay, ingest and web, all targetsjoule-moqand atserver.rs:167,session.rs:302, all on main)wai registry export --check;--lib codecs::registry;--features live_room --test live_room;--features live_metering --test live_meteringcbindgen.tomltouchedinclude/wai.hunchangedlive_rooms_verify.py,live_metering_verify.py,live_record_verify.py,e2ee_verify.pye2e/run.sh --runs 2, real Chrome, seek-back included)--test dvr --test late_joiner, 4 rounds of 16 concurrent copies, load average about 73 (before the merge)The first round after the merge caught that
secure-objectswas on only through the relay's dev-dependency: the relay's own tests passed, while the relay built asjoule-moq-ingest's dependency did not. The feature is now on the normal dependency, andjoule-moq-room's lock gains the crates it brings (additions only, at the versions the joule-code lock holds).Seen earlier, not reproduced after fix 3: in 3 of 64 earlier stress runs, the viewer's WebSocket session didn't end within 40 s of the client closing.
conn.closed()never resolved. That is in the WebSocket binding, not the DVR code, and none of the 64 runs after the pairing fix showed it. If it reappears, the test now prints the open session's diagnostics.The live demo room (not changed by this PR)
To turn DVR on for wai.transaction.science/room/, add to the relay's
relay.tomlon prod:At the room's limits (4 publishers at 1500 kbit/s each), a 15-minute window is about 0.7 GB of media. Each receipts object adds 359 bytes per group, which is negligible next to that.
🤖 Generated with Claude Code
Taking group 3 can evict a media and receipts pair from the cache; the test's media and receipts FETCHes are two requests, so an eviction between them left media without its receipts ("the receipts of group 2 come with it", 16 of 64 runs under load with logging). The test now waits until the relay's largest object of both tracks is group 3's. Co-Authored-By: Claude Opus 5.5 <[email protected]>