Pagination: shared materialized read result #45
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
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?
Context
Follow-up from #9 (PR #44).
docs/technical/cli-api.mdstates: "Pages share a bounded materialized read result; expiry yieldscursor_expiredand requires restarting."The #9 implementation deliberately deviates: the cursor carries only
(offset, filter-hash, expiry), and each page re-queries the backend live. Ordering is deterministic so paging is stable for an unchanged backend, but a concurrent external edit can cause a skipped or repeated item across pages.Why deferred from #9
The acceptance checklist for #9 only requires default limit 50 / clamp 200 / opaque cursor /
cursor_expired. A real materialized page store means daemon-side bounded session state (keyed by cursor), LRU eviction, and restart semantics — infrastructure that belongs with the sync/reconcile work, not the read surface.What to build
as_of.cursor_expired(HTTP 422 / exit 2), requiring the client to restart.Notes
api::serve()and shared via an Axum extension — not per request. Bounds: 16 sessions per route with LRU eviction, TTL 15 minutes (= CURSOR_TTL, so a cursor can never outlive its snapshot). Worst-case residency is 32 sessions × 10,000 items ≈ 96–160 MB in the extreme theoretical case; finite and enforceable for a single-user daemon.as_ofreports the snapshot's capture instant on every page rather than the page-time wall clock, so staleness is disclosed rather than hidden.cursor_expired, 422, exit 2) — an evicted session cannot be mistaken for a different error or silently restarted at offset 0./v1/timelinenow refuses >10,000 instances withlimit_exceededinstead of paging an unbounded result; sanctioned by the spec's bounded-materialized-result requirement and stated in the PR body. Known coverage gap: that refusal path has no test (generating 10k facts is impractical in the suite); the code mirrors the tested tasks/agenda check.Blocked by
None — independent of the read surface, but should land with or after the reconcile/sync machinery (#6 / #36) rather than before it.
Pagination: shared materialized read result (deferred from #9)to Pagination: shared materialized read result