PERF: Files adopts shared revision, snapshot, mutation and delta contracts (#663) #670

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

Context: #663 matrix, DESIGN §58 rules 3–6. This is the Files 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/files/entries; apps/web/src/lib/files/api.ts:41. 8 first pages and 30 s freshness are not revision/byte-keyed bodies. Download conditional reads at lib.rs:3648 are reuse, not coverage for listings/stat.
  • R4: POST /api/v1/files/trash; apps/web/src/lib/files/FilesBrowser.svelte:714. Row removal follows awaited trash. transfer.ts:138 supplies Undo closures; no durable client-ID receipt/inverse shared with other views.
  • R5: GET /api/v1/files/events; crates/plugins/files/src/lib.rs:3834. SSE sends per-path events (256/replay batch, ten-minute retention); client live.ts:23 refetches rather than pulls app-wide deltas. Durable /changes exists to reuse.
  • R6: GET /api/v1/files/entries; apps/web/src/lib/files/api.ts:39. 8 first-page cache entries omit full resident window, cursor chain, selection/scroll and byte limit. Use #549 as seed.

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 rename, move, tag and trash; keep Inspector/Quick Look, parent folder and Calendar references consistent; restore folder sort/filter/cursors and selected item. 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 first pages, listing.rs signed keysets, #452 per-User feed isolation, #627 destination identity, and active #641 job/blaze-surfaces previews. Do not redo decoded-image/traversal work.

Measurement scope: the production/HDD read table on #663 supplies a representative endpoint result, not proof that a complete Files 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/files/entries?limit=100, five serial requests after fixture readiness, all HTTP 200. Median/p95/max 87.8/1069.4/1069.4 ms; five-request burst median/p95/max 2033.2/2034.0/2034.0 ms. Serial window server CPU 1090 ms, RSS 443625472 bytes; no ETag on these sampled responses. Load inside lock 3.32/1.98/0.88.
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 Files 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/files/entries`; `apps/web/src/lib/files/api.ts:41`. 8 first pages and 30 s freshness are not revision/byte-keyed bodies. Download conditional reads at lib.rs:3648 are reuse, not coverage for listings/stat. - R4: `POST /api/v1/files/trash`; `apps/web/src/lib/files/FilesBrowser.svelte:714`. Row removal follows awaited trash. transfer.ts:138 supplies Undo closures; no durable client-ID receipt/inverse shared with other views. - R5: `GET /api/v1/files/events`; `crates/plugins/files/src/lib.rs:3834`. SSE sends per-path events (256/replay batch, ten-minute retention); client live.ts:23 refetches rather than pulls app-wide deltas. Durable /changes exists to reuse. - R6: `GET /api/v1/files/entries`; `apps/web/src/lib/files/api.ts:39`. 8 first-page cache entries omit full resident window, cursor chain, selection/scroll and byte limit. Use #549 as seed. 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 rename, move, tag and trash; keep Inspector/Quick Look, parent folder and Calendar references consistent; restore folder sort/filter/cursors and selected item. 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 first pages, listing.rs signed keysets, #452 per-User feed isolation, #627 destination identity, and active #641 job/blaze-surfaces previews. Do not redo decoded-image/traversal work. Measurement scope: the production/HDD read table on #663 supplies a representative endpoint result, not proof that a complete Files 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/files/entries?limit=100`, five serial requests after fixture readiness, all HTTP 200. Median/p95/max 87.8/1069.4/1069.4 ms; five-request burst median/p95/max 2033.2/2034.0/2034.0 ms. Serial window server CPU 1090 ms, RSS 443625472 bytes; no ETag on these sampled responses. Load inside lock 3.32/1.98/0.88. 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#670
No description provided.