feat(service,host): hold a live read's poll until its rows move
Merged
CH
5h ago+389+389+012345678901234567890123456789-100-100-012345678901234567890123456789
Stacks on #4267, which turns Realtime off by default. Today, with Realtime off, a live read polls every 3 s. This PR makes the poll path near-instant: the service holds each poll until the rows move.
Service (live-procedures.ts, realtime.ts, held-read.ts)
- Digests: each polled part now carries a
digestof its rows. - Holding a poll: a poll can now carry
after=(liveDigestOf: each part's digest, in the parts' name order). The service holds it, re-running the statements every 1 s:- when the rows move, it answers them at once;
- after 25 s, it answers "unchanged": the digests and no rows.
- Reuse: the hold reuses
held-read.ts. Its loop is nowheldUntil, andheldUntilMovedis built on it. - Auth: a poll is authorized exactly as the seal is, through the same procedures, with no new route.
Host (live-follow.ts)
- Re-asking:
liveRowssends the digest it last saw and re-asks after each answer, waiting at least 500 ms between asks. A failed poll is asked again 1 s later, then after longer gaps, up to 5 s. Polling stops when the follow ends or the read is gone. - When the service answers polled: this is the case where Realtime is off or the service couldn't seal. The read is polled quietly and isn't resubscribed every 15 s. This addresses Devin's finding on #4267. A Realtime failure on the host itself still logs and resubscribes.
- Areas: the board and the transcript only pass
afterthrough to their clients.askLivesends a poll withafterunder the held deadline (35 s).
Tests
- Service: a held poll answers within a beat of a change, and answers "unchanged" with no rows at 25 s.
- Host:
- a read answered polled is polled quietly, each poll naming the last digest, and is never resealed;
- a failed poll backs off 1 s, 2 s, 4 s, then 5 s.
- Board and transcript: their existing follow tests still pass.
Made with Luke