fix(vloer): keep health probes constant-cost and page event replay #147
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "ryangr0/vloer-bounded-health-and-replay"
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?
/healthz and /readyz called store.listSessions(), which parsed every
session and decrypted its workspace secret on each probe. Probe cost grew
with history, blocked the event loop, and one corrupt old session made
liveness fail. /healthz now answers without touching storage and /readyz
runs a single SELECT 1 through Store.ping(); both keep their {status,
version} response and GET-only method check.
The live event stream read every event after the client's cursor in one
unbounded query, so a client reconnecting from an old cursor loaded the
whole remainder before backpressure applied. It now reads through
Store.eventPage() in batches of eventReplayBatch (200) rows, continuing
from the last sent id until a short page or a buffered-output limit,
and resumes on the next tick. Store.events() keeps returning the full
remainder for the history endpoint, the engine and the AHP host, so no
caller is truncated.
Store.events() still returns full history for /history, the engine and the AHP host; only the live SSE stream reads in pages of 200. Engine background loops still call listSessions(), so a corrupt session row can still break them (follow-up).
Verified with
mise run verifyon the pinned toolchain (all gates passed).Ticket: https://vikunja.webgrip.dev/tasks/1724
🤖 Generated with Claude Code
/healthz and /readyz called store.listSessions(), which parsed every session and decrypted its workspace secret on each probe. Probe cost grew with history, blocked the event loop, and one corrupt old session made liveness fail. /healthz now answers without touching storage and /readyz runs a single SELECT 1 through Store.ping(); both keep their {status, version} response and GET-only method check. The live event stream read every event after the client's cursor in one unbounded query, so a client reconnecting from an old cursor loaded the whole remainder before backpressure applied. It now reads through Store.eventPage() in batches of eventReplayBatch (200) rows, continuing from the last sent id until a short page or a buffered-output limit, and resumes on the next tick. Store.events() keeps returning the full remainder for the history endpoint, the engine and the AHP host, so no caller is truncated. VIK-1724 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>