PERF: Calendar adopts shared revision, snapshot, mutation and delta contracts (#663) #669

Open
opened 2026-10-02 05:36:11 +00:00 by kayg · 0 comments
Owner

Context: #663 matrix, DESIGN §58 rules 3–6. This is the Calendar adapter issue. The only shared owners are #665 revision cache/ETag, #666 view snapshots, #667 optimistic client IDs/Undo receipts and #668 change stream/deltas. Depend on their public contracts; do not implement competing primitives.

Evidence at c4a61e8cf0:

  • R3: GET /api/v1/calendar/range; apps/web/src/lib/calendar/data.ts:77. 4 range/6 grid/2 year caches are time-keyed, not a revision-keyed body cache with strong conditional reads. Reuse #549.
  • R4: POST /api/v1/notes/journal/log/batch; apps/web/src/lib/calendar/edits.ts:86. Pending client IDs exist, but UndoStep at :307 is a client closure. No common durable receipt and inverse contract.
  • R5: GET /api/v1/files/events; apps/web/src/lib/calendar/data.ts:98. Shares the Files path-hint stream; Notes paths clear all snapshots. No app-wide bounded delta preserves unchanged items.
  • R6: GET /api/v1/calendar/range; apps/web/src/lib/calendar/data.ts:88. Complete grids retained, but caches bound entries, not bytes/rows, and omit a shared selection/scroll snapshot contract. Existing #549 is partial reuse.

Expected:

  • Adopt #665 for list/detail revisions and header-complete rows. Cached open is synchronous, keeps object identity and makes zero requests. Authorize before conditional 304; User switch/revoke/plugin disable removes affected retained data.
  • Adopt #666 for a byte/row-bounded complete view snapshot. Restore before await, then one bounded catch-up; no blank/spinner over already-seen data. Deep-link intent and keyboard focus override a retained view when needed.
  • Adopt #667 for create/move/resize a Log, a Task status change and a queued provider Event edit; restore day/week/Agenda scroll and selected stable ID. Changes publish to every visible/retained representation in one frame. Client IDs survive lost acknowledgement; Undo uses the durable receipt and cannot erase an intervening change. Definite rejection rolls back; timeout remains pending until receipt reconciliation. Do not add offline editing.
  • Adopt #668: one per-User wake-up, coalesced capped deltas, stable unchanged objects and deletion tombstones. Stop full-refetch fan-out and timer refreshes only after the delta covers their correctness duties.

Tests:

  • Production API/e2e for the listed actions and views, including stale 304, lost acknowledgement, duplicate ID, Undo after reconnect/restart, obsolete response, empty/error/offline state and cross-view consistency. Existing status/assertion expectations stay unchanged.
  • Two Users, session switch, share revoke and plugin disable cannot restore denied rows. Keep authorization/step-up and server-only writes through calternal-fs.
  • Pointer/touch (≥44 px), keyboard focus/Enter/Space/Escape, screen-reader name/role/state, Copy link and shortcuts work. Keyboard motion keeps shared durations (#611).
  • Extend #549/#641 profiles rather than create another harness. ≥5 locked production/HDD cold and warm samples; median/p95/max, CPU/RSS and large realistic data plus burst. Cached open ≤100 ms, accepted action ≤150 ms, warm return ≤100 ms, first usable view ≤1.5 s at 10k items. Warm blaze: zero incomplete frames; collect identity/unpainted/long-task/heap/RSS metrics.

Reuse and active work: #549 completed grid/Agenda caches and Journal projection; #609 Week state; #608 preview work; #641 shared blaze harness. Do not redo their fixes.

Measurement scope: the production/HDD read table on #663 supplies a representative endpoint result, not proof that a complete Calendar view meets all budgets. Rule 7/9 findings remain with #641/#549 and the existing surface jobs. This follow-up integrates their results and adds shared-contract acceptance after they land.

Representative measurement from the audit (not a full-view budget result):
/api/v1/calendar/range?from=2026-09-18&to=2026-10-02&tz=UTC, five serial requests after fixture readiness, all HTTP 200. Median/p95/max 64.2/518.9/518.9 ms; five-request burst median/p95/max 107.6/123.7/123.7 ms. Serial window server CPU 290 ms, RSS 286105600 bytes; no ETag on these sampled responses. Load inside lock 3.1/1.9/0.84.
Shared release server source cc25c441b7a974185622a1dee853cf38686d2b67, binary SHA-256 2f3567d91c34839851247bc0acbc25a56aaacd14dca269b8f0342ddf83447ed9; embedded production SPA; Chromium browser on the build host through SSH/HTTPS. Server/Home/Index on perf VM HDD emulator: direct-I/O loop, 8 ms read/write dm-delay, 200 IOPS and 150 MiB/s caps. Every measured phase held flock -w 14400 /root/perf.lock. Qualification QD1 115.3 IOPS/8.028 ms median, QD16 200.7 IOPS/96.993 ms. Fixture: 366 Daily notes, 10,980 Logs, 100 Files/Photos, 20 Notes/Tasks, three Budgets and 100 transactions; Mail empty, Admin one User.
Structural source evidence above is the newer audit base, not the measured binary revision. No claim that these revisions are equivalent. The baseline in docs/perf/baseline.json uses another fixture/build/transport; no regression ratio is valid here. See #663 for matching baseline endpoint values and coverage gaps.

Context: #663 matrix, DESIGN §58 rules 3–6. This is the Calendar adapter issue. The only shared owners are #665 revision cache/ETag, #666 view snapshots, #667 optimistic client IDs/Undo receipts and #668 change stream/deltas. Depend on their public contracts; do not implement competing primitives. Evidence at c4a61e8cf090170f35b1bed3350d9de20c83ecd5: - R3: `GET /api/v1/calendar/range`; `apps/web/src/lib/calendar/data.ts:77`. 4 range/6 grid/2 year caches are time-keyed, not a revision-keyed body cache with strong conditional reads. Reuse #549. - R4: `POST /api/v1/notes/journal/log/batch`; `apps/web/src/lib/calendar/edits.ts:86`. Pending client IDs exist, but UndoStep at :307 is a client closure. No common durable receipt and inverse contract. - R5: `GET /api/v1/files/events`; `apps/web/src/lib/calendar/data.ts:98`. Shares the Files path-hint stream; Notes paths clear all snapshots. No app-wide bounded delta preserves unchanged items. - R6: `GET /api/v1/calendar/range`; `apps/web/src/lib/calendar/data.ts:88`. Complete grids retained, but caches bound entries, not bytes/rows, and omit a shared selection/scroll snapshot contract. Existing #549 is partial reuse. Expected: - Adopt #665 for list/detail revisions and header-complete rows. Cached open is synchronous, keeps object identity and makes zero requests. Authorize before conditional 304; User switch/revoke/plugin disable removes affected retained data. - Adopt #666 for a byte/row-bounded complete view snapshot. Restore before await, then one bounded catch-up; no blank/spinner over already-seen data. Deep-link intent and keyboard focus override a retained view when needed. - Adopt #667 for create/move/resize a Log, a Task status change and a queued provider Event edit; restore day/week/Agenda scroll and selected stable ID. Changes publish to every visible/retained representation in one frame. Client IDs survive lost acknowledgement; Undo uses the durable receipt and cannot erase an intervening change. Definite rejection rolls back; timeout remains pending until receipt reconciliation. Do not add offline editing. - Adopt #668: one per-User wake-up, coalesced capped deltas, stable unchanged objects and deletion tombstones. Stop full-refetch fan-out and timer refreshes only after the delta covers their correctness duties. Tests: - Production API/e2e for the listed actions and views, including stale 304, lost acknowledgement, duplicate ID, Undo after reconnect/restart, obsolete response, empty/error/offline state and cross-view consistency. Existing status/assertion expectations stay unchanged. - Two Users, session switch, share revoke and plugin disable cannot restore denied rows. Keep authorization/step-up and server-only writes through calternal-fs. - Pointer/touch (≥44 px), keyboard focus/Enter/Space/Escape, screen-reader name/role/state, Copy link and shortcuts work. Keyboard motion keeps shared durations (#611). - Extend #549/#641 profiles rather than create another harness. ≥5 locked production/HDD cold and warm samples; median/p95/max, CPU/RSS and large realistic data plus burst. Cached open ≤100 ms, accepted action ≤150 ms, warm return ≤100 ms, first usable view ≤1.5 s at 10k items. Warm blaze: zero incomplete frames; collect identity/unpainted/long-task/heap/RSS metrics. Reuse and active work: #549 completed grid/Agenda caches and Journal projection; #609 Week state; #608 preview work; #641 shared blaze harness. Do not redo their fixes. Measurement scope: the production/HDD read table on #663 supplies a representative endpoint result, not proof that a complete Calendar view meets all budgets. Rule 7/9 findings remain with #641/#549 and the existing surface jobs. This follow-up integrates their results and adds shared-contract acceptance after they land. Representative measurement from the audit (not a full-view budget result): `/api/v1/calendar/range?from=2026-09-18&to=2026-10-02&tz=UTC`, five serial requests after fixture readiness, all HTTP 200. Median/p95/max 64.2/518.9/518.9 ms; five-request burst median/p95/max 107.6/123.7/123.7 ms. Serial window server CPU 290 ms, RSS 286105600 bytes; no ETag on these sampled responses. Load inside lock 3.1/1.9/0.84. Shared release server source `cc25c441b7a974185622a1dee853cf38686d2b67`, binary SHA-256 `2f3567d91c34839851247bc0acbc25a56aaacd14dca269b8f0342ddf83447ed9`; embedded production SPA; Chromium browser on the build host through SSH/HTTPS. Server/Home/Index on perf VM HDD emulator: direct-I/O loop, 8 ms read/write dm-delay, 200 IOPS and 150 MiB/s caps. Every measured phase held `flock -w 14400 /root/perf.lock`. Qualification QD1 115.3 IOPS/8.028 ms median, QD16 200.7 IOPS/96.993 ms. Fixture: 366 Daily notes, 10,980 Logs, 100 Files/Photos, 20 Notes/Tasks, three Budgets and 100 transactions; Mail empty, Admin one User. Structural source evidence above is the newer audit base, not the measured binary revision. No claim that these revisions are equivalent. The baseline in docs/perf/baseline.json uses another fixture/build/transport; no regression ratio is valid here. See #663 for matching baseline endpoint values and coverage gaps.
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
kayg/calternal#669
No description provided.