Repository navigation
perf(cache): use synchronous=NORMAL in WAL mode - #871
Merged
cursor[bot] merged 6 commits intoOct 21, 2026
Merged
Conversation
The cache database runs in WAL mode with SQLite's default `synchronous=FULL`, so every commit waits for a sync of the WAL. Saving a task's result commits twice (the cache entry and the task fingerprint), so each task that misses the cache waits for two syncs before the run moves on. Set `synchronous=NORMAL` when WAL mode is on. In WAL mode this never corrupts the database: a power loss or an OS crash can only roll back the most recent commits, which become cache misses. The WAL is still synced at checkpoints, including the one when the last connection closes. If SQLite can't use WAL (for example, on a network share on macOS), `synchronous` stays `FULL`, because `NORMAL` with a rollback journal can corrupt the database after a power loss. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
cursor
Bot
force-pushed
the
perf/cache-wal-synchronous-normal
branch
from
October 21, 2026 15:47
b65fb24 to
21f3415
Compare
fengmk2
added a commit
to voidzero-dev/vite-plus
that referenced
this pull request
Oct 22, 2026
Bumps vite-task from `8f73655` to `a3c087a`. Changelog: voidzero-dev/vite-task@8f73655...a3c087a#diff-06572a96a58dc510037d5efa622f9bec8519bc1beab13c9f251e97e657a9d4ed ## User-facing vite-task changes - When tasks miss the cache, `vp run` no longer waits for the disk after saving each task's result, so the run finishes sooner. If the computer loses power or the operating system crashes during `vp run`, the cache entries that the run saved can be lost, and those tasks run again next time instead of hitting the cache (voidzero-dev/vite-task#871). No consuming-side code changes were required. Docs are unchanged: the cache guide does not describe write durability or a disk wait after cache misses. There were no earlier unmerged bump pull requests from this automation to close. The previous bump (#3168) is already merged. Draft #3113 is a separate preview branch and was left open. ## Validation - `cargo check --workspace --all-features --all-targets` - `cargo test` for `vp_command`, `vp_error`, `vp_pm_cli`, `vp_js_runtime`, `vp_migration`, `vp_shared`, `vp_static_config`, `vite-plus-cli`, and `vp_global_cli` (all passed) - Snapshot runner compiled as part of the workspace check. The vite-task diff does not change CLI help or snapshot-test crate APIs, so recorded snapshots were not re-recorded. - `Cargo.lock` only updates the vite-task git revision. Crate versions are unchanged from the lockfile that landed with #3168. <div><a href="https://cursor.com/agents/bc-6f3002ad-049c-4fb1-b89b-79405144c7a5?cursor_ref=pr_footer&cursor_cta=open_in_web"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/assets/images/open-in-web-dark.png"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/assets/images/open-in-web-light.png"><img alt="Open in Web" width="114" height="28" src="https://cursor.com/assets/images/open-in-web-dark.png"></picture></a> <a href="https://cursor.com/automations/3a586a0e-cc2b-11f1-bec7-b2318963e0b6"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/assets/images/view-automation-dark.png"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/assets/images/view-automation-light.png"><img alt="View Automation" width="141" height="28" src="https://cursor.com/assets/images/view-automation-dark.png"></picture></a> </div> Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: Charles Wang <wan9chi@users.noreply.github.com> Co-authored-by: Charles Wang <me@wan9chi.com> Co-authored-by: MK (fengmk2) <fengmk2@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Motivation
Every cache commit in
vp runwaits for an fsync of the WAL. The cache opens the database in WAL mode but leaves SQLite's defaultsynchronous=FULL, and saving one task's result commits twice: once forcache_entriesand once fortask_fingerprints. Each cache miss therefore adds two disk syncs before the task counts as finished, so the tasks that depend on it start later.Each run in the chart starts right after
vt cache clean, so every task misses the cache and saves its result. The two workspaces are synthetic pnpm workspaces. Each package has one cached task,build, which is a Node.js script that joins five one-line files intodist/out.js. The 3 packages form a chain (app→lib→utils). Each of the 100 packages depends on 0–3 other packages, chosen by a seeded random generator.Notice that macOS gains almost nothing with this change. This is because a sync there is already fast; SQLite calls
fsync(), and on macOS,fsync()moves the data to the drive, but the drive can keep it in its own cache and write it later (fsync(2)).I haven't measured Windows.
Changes
enable_walfunction, which runsPRAGMA journal_mode=WALand checks the returned mode. It setssynchronous=NORMALonly if the result iswal. WithNORMAL, commits no longer sync; SQLite syncs the WAL at checkpoints, including the checkpoint when the last connection closes.Safety
synchronous=NORMALcan't corrupt the database after a power loss or an OS crash, but it can roll back the most recent commits (SQLite docs). For this cache, a rolled-back commit means a cache miss on the next run, so the task runs again. The cache exists only to save time, so this is acceptable.vp runfirst deletes the old entry's output archive. If the new entry is rolled back, the old entry points to the deleted archive, and the run fails with "Cache restore failed. Runvp cache cleanto clear the cache". This can already happen onmain, because nothing syncs the archives.PRAGMA journal_mode=WALdoes not report an error when SQLite cannot use WAL. It keeps the current mode, usually a rollback journal, and returns that mode's name. With a rollback journal,NORMALhas a small chance of corrupting the database after a power loss, sosynchronousstaysFULLunless the result iswal.synchronousin the file. I checked thatmainand this PR can use the cache entries that the other wrote.