PERF: Notes adopts shared revision, snapshot, mutation and delta contracts (#663) #701

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

Context: #663 matrix, DESIGN §58 rules 3–6. This is the Notes 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/notes/{id}; apps/web/src/lib/api/notes.ts:18. Fetches Note detail each open; JSON etag is not a shared strong HTTP ETag/304 body cache. Existing #639 owns linked-open speed.
  • R4: POST /api/v1/notes; apps/web/src/routes/notes/+page.svelte:57. Create awaits response before item publication. Conditional writes exist, but no shared durable client-ID receipt/Undo contract.
  • R5: GET /api/v1/notes; apps/web/src/lib/notes/noteIndex.svelte.ts:51. Whole-index reload and Files/Notes invalidation are not the shared changed-since sequence plus capped delta.
  • R6: GET /api/v1/notes; apps/web/src/routes/notes/+page.svelte:40. Route owns list/page state; no shared retained rows/cursors/scroll snapshot. General body restoration remains in #639/#641 scope.

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, retitle, edit and trash a Note; restore Navigator/list and Note body/block selection, without causing a write on open. 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: #555 userStorage, #549 Journal projection, #639 linked-open speed, #641 Note traversal, #661 read-induced writes and #634 external edit correctness. Integrate those branches first.

Measurement scope: the production/HDD read table on #663 supplies a representative endpoint result, not proof that a complete Notes 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: corrected GET /api/v1/notes?limit=100 on the locked perf VM, five successful serial reads and five successful concurrent reads. Serial median/p95/max 52.2/69.6/69.6 ms; burst 124.7/125.4/125.4 ms. Response has 100 summary rows and 12,660 bytes; no HTTP ETag. Serial CPU 570 ms, RSS 422936576 bytes; load inside lock 2.7/2.43/1.81. This is a list-read measurement, not body/open/edit acceptance. The first audit used the wrong trailing-slash URI and returned 404; those samples are excluded from this result and retained on #663.

Runtime source cc25c441b7a974185622a1dee853cf38686d2b67, binary SHA-256 2f3567d91c34839851247bc0acbc25a56aaacd14dca269b8f0342ddf83447ed9, shared release server with embedded production SPA. Source evidence above is the newer audit base; do not infer code equivalence. HDD: bench/hdd-emu.sh, direct-I/O loop/ext4/dm-delay 8 ms read/write, 200 IOPS/150 MiB/s caps, flock -w 14400 /root/perf.lock around every phase. QD1 125.0 IOPS/8.028 ms median; QD16 200.9 IOPS/100.139 ms. Fixture: 366 Daily notes, 10,980 Logs, 20 other Notes/Tasks, 100 Files/Photos, three Budgets and 100 transactions. The phase later stopped on an Admin burst transport error before a Note-body probe; no body result is claimed.

Baseline docs/perf/baseline.json Notes list p50/p95 1.3/3.1 ms uses another fixture, build and transport. No controlled regression ratio is valid. #663 records the coverage gap.

Context: #663 matrix, DESIGN §58 rules 3–6. This is the Notes 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/notes/{id}`; `apps/web/src/lib/api/notes.ts:18`. Fetches Note detail each open; JSON etag is not a shared strong HTTP ETag/304 body cache. Existing #639 owns linked-open speed. - R4: `POST /api/v1/notes`; `apps/web/src/routes/notes/+page.svelte:57`. Create awaits response before item publication. Conditional writes exist, but no shared durable client-ID receipt/Undo contract. - R5: `GET /api/v1/notes`; `apps/web/src/lib/notes/noteIndex.svelte.ts:51`. Whole-index reload and Files/Notes invalidation are not the shared changed-since sequence plus capped delta. - R6: `GET /api/v1/notes`; `apps/web/src/routes/notes/+page.svelte:40`. Route owns list/page state; no shared retained rows/cursors/scroll snapshot. General body restoration remains in #639/#641 scope. 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, retitle, edit and trash a Note; restore Navigator/list and Note body/block selection, without causing a write on open. 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: #555 userStorage, #549 Journal projection, #639 linked-open speed, #641 Note traversal, #661 read-induced writes and #634 external edit correctness. Integrate those branches first. Measurement scope: the production/HDD read table on #663 supplies a representative endpoint result, not proof that a complete Notes 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: corrected `GET /api/v1/notes?limit=100` on the locked perf VM, five successful serial reads and five successful concurrent reads. Serial median/p95/max 52.2/69.6/69.6 ms; burst 124.7/125.4/125.4 ms. Response has 100 summary rows and 12,660 bytes; no HTTP ETag. Serial CPU 570 ms, RSS 422936576 bytes; load inside lock 2.7/2.43/1.81. This is a list-read measurement, not body/open/edit acceptance. The first audit used the wrong trailing-slash URI and returned 404; those samples are excluded from this result and retained on #663. Runtime source `cc25c441b7a974185622a1dee853cf38686d2b67`, binary SHA-256 `2f3567d91c34839851247bc0acbc25a56aaacd14dca269b8f0342ddf83447ed9`, shared release server with embedded production SPA. Source evidence above is the newer audit base; do not infer code equivalence. HDD: bench/hdd-emu.sh, direct-I/O loop/ext4/dm-delay 8 ms read/write, 200 IOPS/150 MiB/s caps, flock -w 14400 /root/perf.lock around every phase. QD1 125.0 IOPS/8.028 ms median; QD16 200.9 IOPS/100.139 ms. Fixture: 366 Daily notes, 10,980 Logs, 20 other Notes/Tasks, 100 Files/Photos, three Budgets and 100 transactions. The phase later stopped on an Admin burst transport error before a Note-body probe; no body result is claimed. Baseline docs/perf/baseline.json Notes list p50/p95 1.3/3.1 ms uses another fixture, build and transport. No controlled regression ratio is valid. #663 records the coverage gap.
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#701
No description provided.