Add chat swipe append fast path - #2509
Conversation
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
✅ Bunny Review CompletedTip Review posted. The specimen has left the observation table.
|
🐰 Bunny ReviewBunny Merge Signal: Action NeededWarning ACTION NEEDED
Note Mode: 🧭 Specimen Summary
🔎 Isolated Defects
✅ Resolved Since Last Review
🧹 Nitpicks
🤖 Copy prompt for isolated Bunny findings✅ Control Checks
🧪 Observations
🧰 CI Status
|
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src-tauri/crates/storage/src/lib.rs`:
- Around line 2021-2033: The loop treating any Some(item) from
stage_appended_collection as safe must not trust a mere trailing ']' check;
update stage_appended_collection (the function called in the for loop over
appends) to fully validate that the existing target file is a parseable JSON
array before returning Some(staged_item), and if validation fails return
Ok(None) so the caller falls back to the safe (non-fast-path) commit flow;
specifically, inside stage_appended_collection verify the file parses as a JSON
array (e.g., attempt to deserialize or at least parse the full array structure)
and only prepare/rename the staged file when parsing succeeds, otherwise return
Ok(None) to trigger fallback.
- Around line 640-655: The write lock obtained via self.lock.write() is held
while the update callback is invoked, risking deadlock; change the flow in the
function that calls append_many_and_update_collections_uncached_locked so that
you drop the write guard before invoking the user-provided update closure (i.e.
acquire lock, perform pre-checks like ensure_writes_available() and
any_collection_dirty_cached(...), then release the guard), and then run the
closure outside the lock while using the atomic_update_active flag (like
atomic_update_active used in update_collections_atomically) to detect and fail
fast on re-entrant updates; ensure
append_many_and_update_collections_uncached_locked (and any call sites at lines
~2002-2004) are adjusted to expect the closure to run without the write guard
held.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 0ecaab3c-dcc5-4558-9bc5-5179e698d436
📒 Files selected for processing (3)
src-tauri/crates/storage/src/lib.rssrc-tauri/src/commands/storage/chats.rssrc-tauri/src/commands/storage/message_swipes.rs
| (loaded, original_stamps) | ||
| }; | ||
|
|
||
| let Some(output) = update(&mut loaded)? else { |
There was a problem hiding this comment.
⚠️ MEDIUM: Append validation waits behind update work
Location: src-tauri/crates/storage/src/lib.rs:697
A fascinating inversion: the append-side predicate is presented as the commit-time gate, yet the update closure runs before the append collection is loaded and validated. In the swipe caller, noncanonical sidecars can still trigger parent or extra-collection update logic, closure errors, or captured side effects before the fast path finally returns
Nonefor fallback. The previous precheck refused this poisoned sidecar genealogy before touching the update callback; this version delays the diagnosis until after the callback has already been invited into the laboratory.
Tip
Suggested fix: Validate the append collections before invoking the update closure, or enforce and prove that the callback is sterile enough to run on a path that will be rejected.
Linked issue
Part of #2493
Why this change
What changed
chat_message_add_swipeto fast-path sidecar-backed messages by replacing the parentmessagesrow, appending only newmessage-swipesrows, and applying chat memory invalidation in the same transaction when active content changes.Refactor impact
Primary owner:
Rust storage and chat storage commands.
Impact areas reviewed:
FileStorageappend/update transaction staging, rollback, and cache refresh.chat_message_add_swipeactive/inactive semantics and legacysilentcompatibility.Boundary notes:
src-tauriRust storage/command modules.Noneon unsafe storage shape so the existing full replacement path remains the correctness fallback.Pressure points touched:
ModeSurface,GameSurface, shared mode UI,src-tauri/src/lib.rscommand registration, or import modules.Validation
pnpm typecheck,pnpm build,pnpm check:architecture,pnpm check:docs, or fullpnpm checkwhen warranted)pnpm checkpasses before PR push/handoffManual verification notes
Commands run locally:
cargo test --manifest-path src-tauri/Cargo.toml -p marinara-engine message_swipes_append_cleans_trimmed_legacy_sidecar_rows --libcargo test --manifest-path src-tauri/Cargo.toml -p marinara-engine message_swipes --libcargo test --manifest-path src-tauri/Cargo.toml -p marinara-storage append_many --libcargo check --manifest-path src-tauri/Cargo.toml --workspacerustfmt --edition 2021 --check src-tauri/crates/storage/src/lib.rs src-tauri/src/commands/storage/chats.rs src-tauri/src/commands/storage/message_swipes.rsgit diff --checkpnpm check:architecturepnpm checkDurable test rationale:
Native Tauri large-chat timing:
chat_message_add_swipe: 358.9ms -> 266.4ms on the 5k-message fixture.patchChatMessageExtrawrite still costs 631.0ms, so Phase 3 remains the clearest next latency win.Remaining proof gap:
Feature Discoverability
Check exactly one:
src/features/shell/discovery/because this PR adds or materially changes a user-discoverable feature, workflow, setting, mode, panel, import path, agent, media capability, or advanced tool.Reason:
Docs and release impact
README.mdCONTRIBUTING.mddocs/developer/AGENTS.mdUI evidence
No UI screenshots or recordings. This PR changes Rust storage behavior only.
Summary by CodeRabbit