Skip to content

fix(core): reclaim deleted SQLite pages incrementally - #58730

Open
ganeshgawali2007-arch wants to merge 1 commit into
anomalyco:devfrom
ganeshgawali2007-arch:fix/database-incremental-vacuum
Open

ganeshgawali2007-arch wants to merge 1 commit into
anomalyco:devfrom
ganeshgawali2007-arch:fix/database-incremental-vacuum

Conversation

@ganeshgawali2007-arch

@ganeshgawali2007-arch ganeshgawali2007-arch commented Oct 24, 2026 •

Copy link
Copy Markdown

Issue for this PR

Closes #47591

Type of change

  • Bug fix

What does this PR do?

New databases were created with auto_vacuum=NONE because the SQLite driver enables WAL while opening the file, creating the header before Database can set any pragmas. SQLite ignores later auto-vacuum changes, so deleted pages stayed on the freelist and the file never shrank.

  • Open file databases with WAL disabled, set PRAGMA auto_vacuum=INCREMENTAL before enabling WAL, then continue with the existing pragmas.
  • Reclaim at most 256 free pages after migrations and after an event aggregate is removed (session deletion uses this path), followed by a passive checkpoint.
  • Leave existing NONE/FULL databases untouched; converting them needs an offline VACUUM, which is not safe during multi-process startup.
  • Maintenance is best-effort: a busy database logs a warning instead of failing startup or deletion.

Existing databases created before this change can be converted while OpenCode is stopped:

sqlite3 ~/.local/share/opencode/opencode.db "PRAGMA journal_mode=DELETE; PRAGMA auto_vacuum=INCREMENTAL; VACUUM;"

How did you verify your code works?

  • cd packages/core && bun test test/database-storage.test.ts — 6 pass; 3 of them fail against the previous code.
  • cd packages/core && bun run typecheck — 1,650 files, no type errors.
  • Existing database*.test.ts and bus.test.ts — 85 pass.

Screenshots / recordings

N/A

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

Added by the opencode bot (AI-generated).

Related: #33356, #55282, #54618, #58124

New databases were created with auto_vacuum=NONE because the driver enabled WAL before Database configured any pragmas, so deleted rows stayed on the freelist permanently.

Configure new file databases with incremental auto-vacuum before WAL, and reclaim a bounded number of free pages after migration and after an event aggregate is removed. Existing NONE/FULL databases are left untouched because converting them needs an offline VACUUM.

Fixes anomalyco#47591

@opencode-agent opencode-agent Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Looks good. I reproduced the problem on the base by running the new database-storage tests there: a new database gets auto_vacuum=0, and nothing is reclaimed on reopen or after bus.remove. All of those pass with this change. The nearby database, bus and session suites pass (95 tests) and tsc -b is clean. I couldn't run the CLI end to end in my environment, so the check is at the Database.layer level, which is what #47591's reproduction describes.

I checked the risky spots and found no problems:

  • Both the Bun and Node drivers skip only journal_mode=WAL when disableWAL is set, and WAL is enabled right after the auto-vacuum pragma. On workerd these pragmas are not run at all, as before.
  • Two processes opening the same new file at once is harmless, because a later auto_vacuum pragma is ignored once the header exists.
  • Session deletion is the only caller of bus.remove, and it runs outside any transaction, so the reclaim and checkpoint aren't inside one.

Public API is unchanged.

One note for maintainers: open PR #56365 makes the core part of this same change.

Related: #33356, #55282, #54618, #58124

This branch has not been deployed

No deployments
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.

New and incremental core databases do not reclaim deleted pages during their lifecycle

1 participant