Skip to content

Speed up chat message storage appends - #2504

Merged
Xelvanis merged 2 commits into
refactorfrom
perf/issue-2493-app-speed
Jun 6, 2026
Merged

Speed up chat message storage appends#2504
Xelvanis merged 2 commits into
refactorfrom
perf/issue-2493-app-speed

Conversation

@Xelvanis

@Xelvanis Xelvanis commented Jun 6, 2026

Copy link
Copy Markdown
Contributor

Linked issue

Related to #2493

Why this change

  • Large chats were paying full collection load/rewrite costs when creating new chat messages and initial swipe sidecars. Startup migrations can also warm clean messages and message-swipes caches, which made the append fast path unreachable unless the collections were completely uncached.

What changed

  • Added a transactional append path for multiple uncached storage collections so new message creation can append messages and message-swipes rows together instead of rewriting both full collections.
  • Allowed the append path to proceed when collections are clean-cached, updating those caches after a successful disk append while still refusing dirty cached collections and falling back to the existing full rewrite path.
  • Wired chat message creation with initial swipe sidecars through the append fast path, with fallback to the existing atomic replacement path.
  • Hardened append staging cleanup so preparation errors remove previously created transaction temp files.

Refactor impact

Primary owner:

Rust storage

Impact areas reviewed:

  • src-tauri/crates/storage/src/lib.rs collection append, cache, temp-file rollback, and dirty-cache behavior.
  • src-tauri/src/commands/storage/message_swipes.rs create-message sidecar persistence.
  • Startup-warmed messages / message-swipes cache behavior.
  • Message swipe sidecar tests covering create, materialization, migration, delete, inactive swipes, and extra preservation.

Boundary notes:

  • The change stays in Rust storage/Tauri command ownership.
  • No React feature, TypeScript engine, shared API, or remote-runtime dispatch changes.
  • The fast path falls back to the existing full atomic rewrite path when dirty cached collections or unsafe append conditions are detected.

Pressure points touched:

  • Rust storage crate collection persistence.
  • Storage message swipe command helper.
  • No ModeSurface, GameSurface, command registration, or import modules touched.

Validation

  • Matching validation command passes locally (for example pnpm typecheck, pnpm build, pnpm check:architecture, pnpm check:docs, or full pnpm check when warranted)
  • Full pnpm check passes before PR push/handoff
  • Human/manual validation completed by contributor or reviewer

Manual verification notes

Commands run locally:

  • cargo fmt --manifest-path src-tauri/crates/storage/Cargo.toml -- --check
  • git diff --check
  • cargo test --manifest-path src-tauri/Cargo.toml -p marinara-storage append_many_uncached
  • cargo test --manifest-path src-tauri/Cargo.toml -p marinara-engine message_swipes --lib
  • cargo check --manifest-path src-tauri/Cargo.toml --workspace
  • pnpm check

Manual/native Tauri timing proof was not run yet. Follow-up should compare send and regenerate timings on a large chat.

Feature Discoverability

Check exactly one:

  • Updated 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.
  • N/A because this PR is only a bugfix, refactor, test, docs, internal wiring, visual polish, copy edit, or compatibility fix and does not add a new thing users need to find.

Reason:

  • Internal Rust storage performance fix only; no user-facing feature or workflow is added.

Docs and release impact

  • No docs changes needed
  • Updated README.md
  • Updated CONTRIBUTING.md
  • Updated docs/developer/
  • Updated repo skills or AGENTS.md
  • Confirmed this PR does not restore old staging/package-workspace/release claims

UI evidence

No visible UI changes. Runtime timing proof remains follow-up work for large-chat performance measurement.

Summary by CodeRabbit

Release Notes

  • New Features

    • Added optimized batch append operation for multiple data collections.
  • Refactor

    • Improved performance for newly created message persistence with swipe variants.
  • Tests

    • Added comprehensive test coverage for new batch append operations.

@coderabbitai

coderabbitai Bot commented Jun 6, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: fd8b8f46-00b5-4390-954f-c88fb92c2b89

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch perf/issue-2493-app-speed

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions

github-actions Bot commented Jun 6, 2026

Copy link
Copy Markdown

✅ Bunny Review Completed

Tip

Review posted. The specimen has left the observation table.

  • Commit: bddd27b - Preserve explicit message replacement writes

@github-actions

github-actions Bot commented Jun 6, 2026

Copy link
Copy Markdown

🐰 Bunny Review

Bunny Merge Signal: Ready

Tip

READY
No actionable findings were isolated for this head. Expected CI controls were observed passing.

Findings Nitpicks Controls Reviewed Head Mode
0 0 2 pass bddd27ba incremental

Note

Mode: incremental
Head: bddd27b - Preserve explicit message replacement writes
Base: d73bcc1 - Speed up chat message storage appends

🧭 Specimen Summary

  • The specimen diverts caller-supplied message IDs away from the seductive but unsafe uncached append artery, sending them through atomic replacement where old rows and sidecars can be properly displaced. Generated IDs may still take the fast path, but imported or caller-owned identities no longer gamble on cache state. The experiment is satisfyingly narrow: one message row, current swipe sidecars, and no duplicate genealogy hiding in clean storage.

🔎 Isolated Defects

Tip

No actionable defects isolated.

✅ Resolved Since Last Review

  • src-tauri/src/commands/storage/message_swipes.rs:437 - Fast append skips the existing replacement contract

🧹 Nitpicks

  • None recorded.

✅ Control Checks

Status Type Check Detail
✅ PASS CI Timing CI Status Expected CI controls completed without a reported failure.
✅ PASS Proof Gap Prior Contract 1 The open fast-append contract appears sutured: caller-supplied IDs bypass append_many_uncached, stale sidecars are replaced atomically, and the new tests exercise stale sidecars, post-precheck replacement, and cache-state shape parity.

🧪 Observations

  • Established the packet base d73bcc1 and head bddd27b; only src-tauri/src/commands/storage/message_swipes.rs changed.
  • Read AGENTS.md plus architecture and bugfix discipline guidance; this is a privileged Rust storage repair with no new boundary imports or remote-routing changes.
  • Judged the prior fast-append repair contract first, then traced caller_supplied_id from prepare_message_create_row through create_message and both persistence layers.

🧰 CI Status

  • pass: Frontend, Architecture, and Organization
  • pass: Rust Capability Layer
  • pass: Browser Smoke and Performance
  • note: Bunny gates only required job conclusions from ci-checks.json; advisory reports such as continue-on-error dependency checks are not included in this status.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bunny Review inline findings

Comment thread src-tauri/src/commands/storage/message_swipes.rs
@coderabbitai coderabbitai Bot added the server label Jun 6, 2026
@github-actions github-actions Bot removed the server label Jun 6, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (1)
src-tauri/src/commands/storage/message_swipes.rs (1)

430-466: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

This fast path still fractures create-time uniqueness for explicit IDs.

Still unresolved, Doctor's note: the explicit-ID precheck happens earlier in prepare_message_create_row, before the storage write lock. Two concurrent creates with the same caller-supplied id can both reach this branch and append duplicate messages plus duplicate message-swipes rows, while the fallback path still replaces by message_id. That makes persisted semantics depend on cache state instead of the create contract.

🤖 Prompt for 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.

In `@src-tauri/src/commands/storage/message_swipes.rs` around lines 430 - 466, The
fast-path in append_created_message_and_swipes_if_uncached allows two concurrent
creates with the same caller-supplied id to both succeed because the explicit-ID
precheck in prepare_message_create_row runs before any storage write lock; fix
by ensuring uniqueness is enforced inside the atomic append or by taking the
same write lock/replace semantics as the fallback: either 1) have
state.storage.append_many_uncached check for existing message id (and return
false if present) so append_many_uncached enforces uniqueness for the
("messages", ...) tuple, or 2) move the explicit-ID existence check into
persist_created_message_with_swipes under the same lock used by
write_message_and_swipes so the code path that calls
append_created_message_and_swipes_if_uncached cannot race on caller-supplied
ids; update append_created_message_and_swipes_if_uncached to rely on the storage
append result (state.storage.append_many_uncached) to decide fallback to
write_message_and_swipes.
🤖 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.

Duplicate comments:
In `@src-tauri/src/commands/storage/message_swipes.rs`:
- Around line 430-466: The fast-path in
append_created_message_and_swipes_if_uncached allows two concurrent creates with
the same caller-supplied id to both succeed because the explicit-ID precheck in
prepare_message_create_row runs before any storage write lock; fix by ensuring
uniqueness is enforced inside the atomic append or by taking the same write
lock/replace semantics as the fallback: either 1) have
state.storage.append_many_uncached check for existing message id (and return
false if present) so append_many_uncached enforces uniqueness for the
("messages", ...) tuple, or 2) move the explicit-ID existence check into
persist_created_message_with_swipes under the same lock used by
write_message_and_swipes so the code path that calls
append_created_message_and_swipes_if_uncached cannot race on caller-supplied
ids; update append_created_message_and_swipes_if_uncached to rely on the storage
append result (state.storage.append_many_uncached) to decide fallback to
write_message_and_swipes.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 1ffe2293-3a61-4dbe-80f8-d8d8b7931325

📥 Commits

Reviewing files that changed from the base of the PR and between 0e273fe and d73bcc1.

📒 Files selected for processing (2)
  • src-tauri/crates/storage/src/lib.rs
  • src-tauri/src/commands/storage/message_swipes.rs

@Xelvanis
Xelvanis merged commit 29dc711 into refactor Jun 6, 2026
8 checks passed
@Xelvanis
Xelvanis deleted the perf/issue-2493-app-speed branch June 6, 2026 16:04
@Promansis Promansis mentioned this pull request Jun 6, 2026
11 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant