Follow-up: carry PR #701's stranded review fixes (skip the wasted resettle scan, MaintenanceReport symmetry, span visibility, LLP gloss) - #706
Conversation
… MaintenanceReport symmetry, span visibility, LLP gloss PR #701 was squash-merged at head 287b67b, before the round-2 review fixes in cc82d6f were pushed, so four verified fixes never reached master. - Hoist a cheap `compactionDue` check above the `hasResettleCandidate` row scan and gate the scan on `!compactionDue`. Recognition of a foreign sorted `replace` outranks the resettle check, so the first tick after each foreign replace paid a complete single-column scan of the day purely to discard the answer. - Add `totalRebaselined` to `MaintenanceReport` beside `totalCompacted`, and let `query.js` read it instead of re-deriving the count. - Tag the enclosing `maintenance.partition` span with `rebaselined`; the `hyp_rebaselines` counter carries only the dataset, not the partition. - Give LLP 0199's bare `Extended-by: LLP 0207` the corpus's linked and glossed form. Co-Authored-By: Claude <noreply@anthropic.com>
Round-1 review of #706 approved the carry but flagged that none of the four stranded fixes was pinned by a committed test, plus two @ref nits. - Add three tests to test/core/cache-retention-maintenance.test.js, in the foreign-sorted-replace block: - `totalRebaselined === 1` on a re-baselining run, and `=== 0` once converged (pins the MaintenanceReport symmetry fix). - a capturing TracerProvider asserting the maintenance.partition span carries `rebaselined: true` (pins the span-attribute fix). - a partition already due for compaction: assert the resettle candidate's data file is read once, not twice, by spying on `fs.readFileSync` (pins the scan-skip fix). hasResettleCandidate's return value is otherwise unobservable once compactionDue is true (it's discarded via `||`), so this is the cheapest honest signal available; each new test was verified to fail when its corresponding fix is reverted. - Retarget the scan-skip gate's @ref from LLP 0207#foreign-replace to #outranks-resettle: the gloss ("recognition ... still outranks it") is that anchor's actual subject, not the recognition test's. - Drop the @ref on the span-attribute comment: #re-baseline settles the cursor-write shape, not telemetry, so citing it was close to mechanical. The prose rationale stays; it's the useful part. - Amend the PR body's claim about item 1: `needsCompaction` (pure, read-only) is now evaluated unconditionally in the re-settle path where the old `||` short-circuited past it, so more moved than "only the scan's side effect is skipped." Co-Authored-By: Claude <noreply@anthropic.com>
Review round 1 - head
|
- test/core/cache-retention-maintenance.test.js: the resettle-scan-skip test asserted a global .parquet readFileSync count of 1 for the whole maintainCache tick, not just reads the gate governs. Any future second legitimate read elsewhere in the tick would break it with a message that misdirects the next reader. Switch to capturing a stack trace per .parquet read and asserting none pass through hasResettleCandidate, attributing each read to its caller instead of counting tick-wide. Verified both directions: passes at this head (3x, no flake), and fails with the expected message when the !compactionDue && gate in src/core/cache/maintenance.js is reverted, showing hasResettleCandidate in the offending stack. - PR body: item 2's exemplar list cited llp/0012:9, 0017:9, 0036:9, 0041:8, 0191:9 as using the linked-and-glossed Extended-by form, but only 0191 actually carries a link; the other four are gloss-only. Replaced with docs confirmed to use the linked form: llp/0106:9, 0129:9, 0158:9, 0180:9, 0182:9, 0188:9, 0190:9, 0191:9. (0201, also suggested, only has a backward "Extends" pointer, not "Extended-by", so it was excluded.) Co-Authored-By: Claude <noreply@anthropic.com>
Review round 2 - head
|
Neutral triage at head
|
Why this exists
PR #701 went through review, a fix worker applied four round-1 items and pushed
cc82d6ffd96e2216f4c219f349c107d06a046ee2, and then #701 was squash-merged athead
287b67bb- beforecc82d6flanded. #701 is nowMERGEDand closed,so its branch is invisible to the reconciler and the four verified fixes would
be silently lost.
Evidence that they never reached master:
git merge-base --is-ancestor cc82d6f origin/master-> falseorigin/master:src/core/cache/maintenance.jscontains zero occurrences ofcompactionDueorigin/master:src/core/cache/maintenance.jscontains zero occurrences ofsetAttribute('rebaselined'origin/master:src/core/cache/types.d.tscontains zero occurrences oftotalRebaselinedAll four files
cc82d6ftouches are byte-identical between287b67bandcurrent
origin/master, so each fix is carried over unchanged in intent.The four fixes
1. Skip the wasted re-settle scan (
src/core/cache/maintenance.js)Hoist a cheap
const compactionDue = opts.force || (grewSinceCompaction && needsCompaction(liveDir, cfg))above the
hasResettleCandidaterow scan, gate the scan on!compactionDue && settle,and set
shouldCompact = compactionDue || hasResettle.Recognition of a foreign sorted
replaceoutranks the re-settle check, so onthe first tick after each foreign replace a partition with no fallback row paid
a complete single-column scan of the day purely to discard the answer. The
boolean is unchanged (
compactionDue || hasResettleis the same disjunction asbefore); the row scan is skipped when its answer cannot matter. In exchange,
the cheap
needsCompactionstat-walk is now evaluated in the re-settle pathwhere the old
||short-circuited past it:needsCompactiononly reads(
readdirSync/statSync), so this trades a warm stat-walk for a fullsingle-column row scan with no semantic change.
Empirical verification (instrumented
hasResettleCandidatewith a callcounter, then reverted before committing):
test/core/cache-retention-maintenance.test.jstest/core/cache-resettle-sweep.test.jsThe 4 remaining calls are exactly the cases where the fallback-row scan is the
only possible trigger for compaction, so the sweep keeps working; the 4
eliminated calls are scans whose answer was discarded.
2. LLP 0199
Extended-bygloss (llp/0199-maintenance-compaction-convergence.decision.md)Give the bare
**Extended-by:** LLP 0207the corpus's usual linked + glossedform, matching
llp/0106:9,llp/0129:9,llp/0158:9,llp/0180:9,llp/0182:9,llp/0188:9,llp/0190:9,llp/0191:9.3.
MaintenanceReportsymmetry (types.d.ts,maintenance.js,commands/query.js)Add
totalRebaselined: numbertoMaintenanceReportand increment it besidetotalCompacted, soquery.jsreads the total the report already knows insteadof re-deriving it by filtering
report.partitions.maintainCacheis the onlyproducer of a
MaintenanceReport, so the new required field has one writer.4.
rebaselinedspan attribute (src/core/cache/maintenance.js)The
hyp_rebaselinescounter was the only in-daemon signal that a re-baselinehappened, and it carries only the dataset, not the partition. Tag the enclosing
maintenance.partitionspan so a trace query can find which day re-baselined.Note on PR #698
Open PR #698 (
fix/issue-697) rewrites this file heavily (streaming row groups,descriptor parking) and adds its own
span.setAttributeblock inmaintainCache, converting thewithSpancallback toasync (span) =>. Toavoid a needless conflict, item 4 here is deliberately not the original
cc82d6fshape (which restructured that same callback intoconst result = ... ; span.setAttribute(...) ; return result). Instead it is asingle line at the re-baseline site itself, using the repo's existing
getActiveSpan()helper (already used insrc/core/commands/policy.js):withSpanruns its callback undertracer.startActiveSpan, so the enclosingmaintenance.partitionspan is the active span there; instrumentation confirmedgetActiveSpan()resolves to a real span in all 4 re-baseline paths exercised bythe suite. This leaves the exact block #698 rewrites untouched.
Verified:
git merge origin/fix/issue-697into this branch auto-mergessrc/core/cache/maintenance.js,src/core/cache/types.d.tsandsrc/core/commands/query.jscleanly. The only conflict is the one-line**Extended-by:**metadata field inllp/0199, which #698 also rewrites (itadds a gloss for 0207 and 0209 but no link); resolving it is a union of the two
glosses.
Gate
npm test: 3901 pass, 0 fail, 6 skippednpm run typecheck: cleantest/core/llp-ref-hygiene.test.js: 11 pass, 0 failhyp smoke cache_lifecycle_maintenance: okhyp smoke incremental_sink_compaction: okhyp smoke cache_roundtrip: okIssue #700 was already closed by #701; this PR deliberately carries no
Fixes #...trailer.🤖 Generated with Claude Code