Skip to content

fix(db): extract WAL maintenance, surface TRUNCATE no-op - #12853

Merged
diegosouzapw merged 1 commit into
cheaper-inference:release/v3.8.51from
maxmad64bis:fix/batch10-wal-maintenance
Sep 8, 2026
Merged

diegosouzapw merged 1 commit into
cheaper-inference:release/v3.8.51from
maxmad64bis:fix/batch10-wal-maintenance

Conversation

@maxmad64bis

@maxmad64bis maxmad64bis commented Sep 6, 2026 •

Copy link
Copy Markdown
Contributor

⚠️ base-red inherited: #12732

Summary

A long-running server never closes its DB, so the only thing reclaiming the WAL file is the periodic wal_checkpoint(TRUNCATE) — and until now that checkpoint never actually looked at its own result. checkpointDb ignored the pragma return and always reported success, so a checkpoint that hit a busy database silently did nothing and the next try came 6 hours later. It's the kind of bug you only notice when the WAL file is suddenly bigger than the database itself.

This moves the whole WAL lifecycle out of core.ts into src/lib/db/walMaintenance.ts. The new module reads the checkpoint result row: a busy checkpoint now warns with its streak (... still busy (streak 3)) and schedules one lightweight PASSIVE retry a minute later (which moves pages without waiting on writers; shrinking stays the next TRUNCATE tick's job). Closing-time checkpoints no longer print success on builds that never had a database file. core.ts just calls in — about 50 lines lighter, no signature changes for operators.

The busy totals also surface in the authenticated monitoring health payload (walMaintenance key: ticks, current streak, lifetime busy count, last busy/ok timestamps), so an operator watching contention over time doesn't have to grep logs. Deliberately no persisted counter: the streak lives in memory and resets on stop.

Related Issues

Validation

  • Change type: DB
  • Focused tests and category gates from the golden path
  • npm run lint
  • Reconciled with the current active release base; focused checks rerun afterward
  • Production-code changes include a new or updated automated test in this PR
  • SonarQube is temporarily opt-in while the private project has no quota; it is not a PR gate.

Tests Added Or Updated

  • tests/unit/wal-maintenance.test.ts (new, 11 tests): busy/clean/sentinel--1/bare-object/undefined-null-[] parsing, pragma-throw never propagates, guarded ctx skips, interval parsing (default/garbage/0), __resetForTests, start silent under test gate, bun:sqlite checkpoint shape (passes under bun test, skips under Node).
  • tests/unit/db-wal-truncate-scheduler.test.ts (rewritten 5 wiring tests + 1 new close-table test): new anchors on ./walMaintenance import, startWalMaintenance(db / stopWalMaintenance() / runCheckpointNow, env literal + 6h default + self-gate in the new module, streakBefore ctx at close.
  • tests/unit/observability-payloads.test.ts (+1 test): walMaintenance allowlist projection — documented scalars pass, timer internals never leak, null state degrades to null.
  • Neighbors green: tests/unit/db-core-init.test.ts (14/14, incl. checkpointMode: null pin), tests/unit/db/vacuum-scheduler.test.ts (11/11), combined WAL+vacuum single-process run (21/21, shared resetter coupling).

Coverage Notes

  • Change touches src/lib/db/ (walMaintenance.ts new, core.ts rewired) plus an additive health key (observability.ts, health route). Covered by the new wal-maintenance.test.ts (every outcome branch: busy/clean/sentinel/bare-object/fail-open×3/throw/skipped) plus the rewritten scheduler wiring tests plus the new projection test. No coverage regression expected — new code ships with its tests in the same PR; core.ts only loses deleted lines.

Reviewer Notes

  • Two deliberate behavior changes to be aware of: (1) a busy checkpoint at close now warns instead of logging success — that's the visibility fix itself, called out here so it's not mistaken for a regression; (2) the PASSIVE retry costs one extra cheap checkpoint per busy event max, never re-arms, never touches the WAL shrink path.
  • walMaintenance.ts never imports ./core (cycle gate clean); clearDbHealthCheckScheduler() ordering in closeDbInstance preserved so no timer leaks. Health addition is one additive key (walMaintenance), management-auth-gated like the rest of the payload — nothing existing moves.
  • Verified: focused tests 52 pass / 0 fail (+1 Bun-only skip under Node), typecheck:core clean, ESLint clean on changed files, check:cycles OK, check:file-size silent, check:docs-counts drift is pre-existing (169→170 migrations, untouched). test:bun:db 22/22.

@maxmad64bis
maxmad64bis force-pushed the fix/batch10-wal-maintenance branch 3 times, most recently from 564d0a6 to b10f35d Compare September 6, 2026 12:02
@maxmad64bis
maxmad64bis force-pushed the fix/batch10-wal-maintenance branch from b10f35d to ef1bdbb Compare September 6, 2026 15:07
@diegosouzapw
diegosouzapw merged commit 2959337 into cheaper-inference:release/v3.8.51 Sep 8, 2026
8 of 16 checks passed
diegosouzapw added a commit that referenced this pull request Sep 17, 2026
…-09-15) (#13731)

Second `npm run release:reconcile` pass on `release/v3.8.50..release/v3.8.51`
(0915890..c0f92ec, 916 non-merge commits, 877 merged PRs):

- fold the 173 changelog.d fragments accumulated since #12971 under
  `## [3.8.51]` and delete them
- generate bullets for the 58 cycle commits that had no fragment
  (4 features / 42 fixes / 12 maintenance), each with the merged PR link and
  `— thanks @author`
- link 137 fragment bullets to the PR of the commit that added them and
  credit the author; two prefix/origin mismatches reviewed (#12945→#13392,
  #13001→#13379, both maintainer rebaselines of other people's PRs)
- refresh "Release by the numbers" + Top-25 and regenerate the
  `### 🙌 Contributors` hall (112 external contributors + maintainer; every
  non-bot author of the 877 merged PRs present)
- closed-PR credit audit for the window: nothing to add (#13215→#13361 and
  #13059→#13690 are still open, #12998 was independently fixed earlier by
  #12853); no human co-author trailers, no commits without a PR
- resync the 58 i18n CHANGELOG mirrors

Gates: check:changelog-integrity OK, check:docs-sync PASS.
@maxmad64bis
maxmad64bis deleted the fix/batch10-wal-maintenance branch September 24, 2026 21:12
muhamadgalihsaputra pushed a commit to niyatna/NiyatnaRoute that referenced this pull request Sep 27, 2026
…erence#12853)

Validado numa worktree combinada com a onda de persistência desta leva sobre `release/v3.8.51`: check-file-size e check-changelog-integrity OK, typecheck:core limpo, check-api-typecheck OK (289, dentro da baseline), 70 testes focados no runner Node e 1 no vitest, todos verdes.

"Um checkpoint que nunca olhou o próprio resultado" é o tipo de defeito que só aparece quando o WAL fica maior que o banco. Ler a linha de retorno do pragma e diferenciar busy de sucesso é a correção; o retry `PASSIVE` um minuto depois é o que evita esperar as 6 horas do próximo tick.

Gostei da decisão de não persistir contador: streak em memória que zera no stop é o comportamento honesto para uma métrica de contenção.

Os 11 casos cobrem as formas de retorno que o pragma pode assumir — sentinela `-1`, objeto pelado, `undefined`/`null`/`[]` — que é onde esse tipo de parsing costuma quebrar em silêncio.
muhamadgalihsaputra pushed a commit to niyatna/NiyatnaRoute that referenced this pull request Sep 27, 2026
…-09-15) (cheaper-inference#13731)

Second `npm run release:reconcile` pass on `release/v3.8.50..release/v3.8.51`
(104d4f8..d61b804, 916 non-merge commits, 877 merged PRs):

- fold the 173 changelog.d fragments accumulated since cheaper-inference#12971 under
  `## [3.8.51]` and delete them
- generate bullets for the 58 cycle commits that had no fragment
  (4 features / 42 fixes / 12 maintenance), each with the merged PR link and
  `— thanks @author`
- link 137 fragment bullets to the PR of the commit that added them and
  credit the author; two prefix/origin mismatches reviewed (cheaper-inference#12945→cheaper-inference#13392,
  cheaper-inference#13001→cheaper-inference#13379, both maintainer rebaselines of other people's PRs)
- refresh "Release by the numbers" + Top-25 and regenerate the
  `### 🙌 Contributors` hall (112 external contributors + maintainer; every
  non-bot author of the 877 merged PRs present)
- closed-PR credit audit for the window: nothing to add (cheaper-inference#13215→cheaper-inference#13361 and
  cheaper-inference#13059→cheaper-inference#13690 are still open, cheaper-inference#12998 was independently fixed earlier by
  cheaper-inference#12853); no human co-author trailers, no commits without a PR
- resync the 58 i18n CHANGELOG mirrors

Gates: check:changelog-integrity OK, check:docs-sync PASS.
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.

2 participants