Repository navigation
fix(db): let current compression engine rows win over legacy keys - #15607
Merged
diegosouzapw merged 4 commits intoOct 6, 2026
Merged
diegosouzapw merged 4 commits into
diegosouzapw merged 4 commits into
Conversation
getCompressionSettings read the compression namespace with no ORDER BY and mapped the legacy keys aggressiveConfig/ultraConfig/headroomConfig onto the same fields as aggressive/ultra/headroom, so the row read second won. With the (namespace, key) primary-key index that was always the longer legacy key: on a database holding a legacy row (manual SQL, outside tool, or a database from another build), every engine-page save returned 200 while GET and live compression kept serving the legacy values. Skip a legacy key when its current key is present in the same read. A legacy row with no current counterpart still applies, and a parsed non-object legacy value still resets the engine to defaults.
…t-row precedence Review follow-up: the legacy-only fallback was tested for one of three engine pairs, the test file had partial literals that fail tsc under Partial<CompressionConfig>'s nested full-shape rule, and the deliberate presence-based precedence (a corrupt current row suppresses a valid legacy row) was undocumented. Adds the missing ultra/headroom fallback tests, the corrupt-row pin, spreads the exported defaults into the literals, and states the invariant on the read path.
Ship coverage-audit follow-up: pins the second diegosouzapw#13456 corruption mode — an unparseable-JSON current row still shadows a valid legacy row, and an unparseable legacy-only row resets the engine to defaults.
diegosouzapw
merged commit Oct 6, 2026
ed9188f
into
diegosouzapw:release/v3.8.52
43 of 51 checks passed
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.
Summary
getCompressionSettings(src/lib/db/compression.ts:674) reads the compression namespace withSELECT key, value FROM key_value WHERE namespace = ?and no ORDER BY. Its read cases map the legacy keysaggressiveConfig,ultraConfigandheadroomConfigonto the same fields as the current keysaggressive,ultraandheadroom, so the row read second wins. The query walks the(namespace, key)primary-key index, and the legacy key always sorts after the current key it shadows. On a database holding a legacy row (manual SQL, an outside tool, or a database written by another build; no app write path creates one), every save on the Aggressive, Ultra or Headroom engine page returned 200 while GET and live compression kept serving the legacy values. A read-only repro confirmed it: with legacy rows present, savingaggressive.maxTokensPerMessage=4096,ultra.compressionRate=0.9andheadroom.minRows=50still read back 1111, 0.1 and 3.The fix builds a Set of the keys present in the read and skips a legacy key when its current key is present in the same read. The bug came from relying on unspecified row order, so the fix stays order-independent instead of picking a new ORDER BY.
Behavior kept on purpose:
Commits:
Test Coverage
Tests: 6783 → 6783 tracked test files; the new file holds 10 tests.
Pre-Landing Review
Five specialists (testing, maintainability, security, performance, simplification) plus Claude and Codex adversarial passes reviewed the diff. Five informational findings: three fixed (legacy-fallback coverage for ultra/headroom, tsc-clean test literals, corrupt-row precedence pinned with a test and a comment), two declined with recorded reasons: a warn on every suppressed legacy row (permanent state on a 5s-hot read path; chronic log noise), and legacy-row retirement (needs a migration; separate scope). Codex adversarial: no actionable defects.
Known limits
Verification Results
Documentation
Status: current — no documentation edits required. Audited the branch diff (3 commits, 2 files) against 12 docs; all reviewed docs remain factually accurate. The fix changes internal DB read precedence that no documentation described before or after.
Documentation debt: legacy engine-row precedence and the corrupt-row reset behavior have zero doc coverage; a note in docs/compression/COMPRESSION_ENGINES.md would fill both.
Test plan
node --import tsx/esm --test tests/unit/compression/*.test.ts(9 DB-layer files): 60 pass / 0 failnpm run test:vitest: passnpm run typecheck:core: clean