Repository navigation
db: keep startup fail-closed on a missing SQLite file - #447
rain-marvin[bot] wants to merge 1 commit into
Conversation
How to use the Graphite Merge QueueAdd the label add-to-gt-merge-queue to this PR to add it to the merge queue. You must have a Graphite account in order to use the merge queue. Sign up using this link. An organization admin has enabled the Graphite Merge Queue in this repository. Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue. This stack of pull requests is managed by Graphite. Learn more about stacking. |
|
@coderabbitai full review |
✅ Action performedFull review finished. |
|
Navigate logical layers of code changes, visualize relationships, and explore their blast radius. 🧰 Additional context used📚 Code guidelines (1)No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configuration
📒 Files selected for processing (3)
Included review availability: This review used your included allowance. 0 included reviews remain after this review. Your included PR review attempts over the past 7 days set your current allowance at 1 review per hour. WalkthroughThe pool documentation states that neither pool enables Priority: ➖ Normal Merge Risk: ⚪ Minimal · up to The documented startup behavior matches the pool configuration; no issue identified here needs to be resolved before merging. 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
Full details: Docstring CoverageExplanation Docstring coverage is 75.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 4 functions across 2 files. (1 skipped: 1 unsupported.)
✨ Finishing Touches 💡 2📝 Generate docstrings 💡
🛠️ Fix failing CI checks 💡
Comment |
0834d51 to
8fe1758
Compare
|
@kaisbaccour #447, now at To stop me driving this stack, say “pause #447”. |
|
🔎 Reviewing |
There was a problem hiding this comment.
This PR sets create_if_missing(true) on both SQLite pools (the event store pool and the apalis job pool), so the bot creates issuance.db and runs migrations when the file is missing, instead of exiting with SQLite error 14. It adds tests/fresh_database.rs to prove that startup now creates the file.
The code change does what the description says. But the old behavior was a deliberate safeguard, not a bug. docs/nixos-provisioning.md (Database section) says the service opens SQLite with create_if_missing = false on purpose, because a missing file means a wrong path or an unmounted volume. It also says the error 14 crash loop on a fresh host is "the fail-fast working as intended", and that the operator creates the file once by hand. src/burn_excess/cli.rs keeps create_if_missing(false) for the same reason. This PR removes that guard, and it does not update the runbook. The fix for a fresh disk is the documented one-time install ... /dev/null /mnt/data/issuance.db step. If the team wants automatic creation, it should be an explicit opt-in, with a mount check on the service. One blocking finding.
Verdict: Request changes. I opened this PR, and GitHub does not let an author approve or request changes, so the verdict is in the rain-marvin/reviewed check.
claude-opus-5-5 · high · 8 min
8fe1758 to
081d333
Compare
|
@kaisbaccour #447, now at To stop me driving this stack, say “pause #447”. |
|
@coderabbitai review |
|
🔎 Verifying that my findings from |
✅ Action performedReview finished.
|
There was a problem hiding this comment.
This PR no longer changes runtime behavior. The server keeps opening SQLite without create_if_missing, so a missing database file still stops startup with error 14. The PR adds a code comment in create_pool, a runbook sentence saying ?mode=rwc in DATABASE_URL is the only way to opt in to creating the file (never in staging or production), and two tests in tests/fresh_database.rs that pin both sides of that rule.
Earlier findings:
- Resolved: removing the fail-closed guard on a missing SQLite file (
src/lib.rs). At081d333, neithercreate_pool(sqlx 0.9) norcreate_apalis_pool(apalis/sqlx 0.8) setscreate_if_missing, so both use the sqlx default (false) unless the URL carriesmode=rwc. The runbook keeps the manualinstall ... /mnt/data/issuance.dbstep.startup_fails_without_creating_a_missing_database_fileruns the realinitialize_rocketand checks that it fails with "unable to open database file" and leaves no file.startup_creates_a_missing_database_file_with_mode_rwcchecks the opt-in. I rancargo test --test fresh_databaseat081d333and both tests pass. Not settingcreate_if_missing(false)explicitly is the right call, because that would override themode=rwcopt-in the whole test suite relies on.
Threads resolved by hand: none. The only thread was resolved by the bot after the fix above, and the code backs it.
No commits since my last review (head is still 081d333). I found no new problems in the full PR diff. CI (static, test) was still running when I checked.
Verdict: Approve. I opened this PR, and GitHub does not let an author approve or request changes, so the verdict is in the rain-marvin/reviewed check.
claude-opus-5-5 · high · 2 min
|
@kaisbaccour #447 is ready for human review: both bot reviews pass on To stop me driving this stack, say “pause #447”. |
|
@kaisbaccour 🔔 Follow-up: a day after my review @kaisbaccour, #447 hasn't changed since I marked it ready yesterday. It's still on claude-opus-5-5 · high · 15 s |
|
@rain-marvin what's the point of this change? You modified two comments and added a test? |
|
@ueco-jb You're right, and there's not much left in it now. The PR started as a fix for
So it's a regression guard for a mistake that already happened once, and that's all. If you think that's worth an anvil-backed integration test, merge it. I'd drop the claude-opus-5-5 · high · 25 s |
A missing database file means a bad path or an unmounted volume, so the server must not create an empty database and serve with no history. Keep both pools without `create_if_missing`, document that `?mode=rwc` in the URL is the only opt-in, and test both contracts: a missing file fails startup and is not created, and `mode=rwc` creates it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
081d333 to
458aff9
Compare
|
@kaisbaccour #447, now at To stop me driving this stack, say “pause #447”. |
|
@kaisbaccour #447 is ready for human review: both bot reviews pass on To stop me driving this stack, say “pause #447”. |

On a fresh disk the issuance bot exits at startup with
(code: 14) unable to open database file. This PR keeps that behavior, on purpose, and pins it with tests. A missing file means a bad path or an unmounted volume. If the bot created an empty database there, it would serve with no event history, no enabled assets and no receipt inventory. docs/nixos-provisioning.md already documents the fail-closed contract and the one-timeinstall … /mnt/data/issuance.dbstep.Live effect: none. Startup behavior does not change; this adds a code comment, a runbook sentence and tests. · Risk: low · Ships: next release
Decisions
create_if_missingon either server pool. An earlier version of this PR set it totrue, and review showed that this removed the documented guard (thread).?mode=rwcinDATABASE_URLas the only opt-in, instead of adding an env flag. sqlx already parses it, and the test suites already use it. The runbook now says never to set it in staging or production.create_if_missing(false), because that would overridemode=rwcand remove the opt-in.Proof
tests/fresh_database.rs::startup_fails_without_creating_a_missing_database_file:initialize_rocketagainst a missing file with nomode=rwcfails with "unable to open database file", and the file still does not exist.tests/fresh_database.rs::startup_creates_a_missing_database_file_with_mode_rwc: the same start with?mode=rwccreates the file.cargo fmt,cargo check --workspace --testsandcargo clippy --workspace --all-targets --all-features -D warningspass locally.🤖 Generated with Claude Code