Repository navigation
Conversation
`promote` no longer re-reads a manifest staged by the same `PartWriteTxn`, so the "body-absent precommit is rejected" contract now applies only to manifests not staged there. Also document that `staged_manifest_proofs` entries must never be erased, because `precommitAdd` uses them as the A3 barrier. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Extract `blobDependenciesOf` so `stageManifest` and the non-staged path of `promote` use the same filter. Cleanup of staged manifests now logs at debug level when the exact-incarnation remove returns `Gone` or `Mismatch`, or throws, instead of silently swallowing it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Add a test that promotes its own staged manifest with Inline and Blob entries: it fails with `no dependency proof` while one blob is missing, then commits without a manifest read. Add a test that `abandon` keeps the live precommit body and removes another staged manifest without `HEAD`. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The record only says what a confirmed put-if-absent returned in `stageManifest`. It does not prove that the body still exists at `promote` time, so "proof" overstated it. Rename the member to `staged_manifests` and say "record" in the docs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The blob dependencies of a `StagedManifest` keep the order the caller passed the entries, which can differ from the path-sorted encoded body. `promote` does not detect a staged body removed outside the protocol; the read path and `fsck` report it later. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Add `FixRecheckAfterFloor` (cut C, floor on every key, owner view, catalog re-read C' for rowless candidates), `ViewByCutLife` (owner view replays the life C named), `PromoteSkipsOwnBodyReread` and the candidate `RecheckLifeChange`. - `fix_recheck_norebirth`, `fix_recheck_noreread_norebirth`: green. - `sab_recheck`: `INV_NO_DANGLE`. - `fix_recheck`: `INV_NO_DANGLE` when the namespace is removed and reborn between C and the floor read; `fix_recheck_life` closes it (green). - `fenced_late_bound_recheck` green, `fenced_late_unbounded_recheck` red: the late-request residual is unchanged. Related: Altinity#2528 Signed-off-by: Mikhail Filimonov <mfilimonov@altinity.com> Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Reproduce a namespace changing incarnation after the sweep catalog cut. The old owner view is empty while the successor life commits the same manifest, so the stale candidate must be retained.
A namespace can change incarnation after the sweep catalog cut while the successor life commits the candidate manifest. Recheck every candidate row by full value and retain it when the catalog life changed.
PR #2528 Audit Review
VerdictNo High-severity defect. The central safety argument holds, and the orphan-sweep change that makes it hold is the right companion fix. Two Medium findings about what the pool leaks and what it no longer detects, and four Low findings. What the change does
The PR replaces it with a proof the writer already holds. A successful Two things fall out of the same record:
Model
The central argument, and why it holdsTrusting an in-memory proof needs exactly one thing: nothing in the protocol may delete a staged The PR earns this by moving the floor gate in A live build cannot be covered by the floor. The second half of the sweep change covers the window the first half opens. The floor read now
I checked the other deletion paths — FindingsRecovery and rollbackMedium: pre-precommit manifest debris becomes permanently unreclaimable when the server root has no
Partial and gray failureMedium: an out-of-protocol body deletion now produces a committed ref to a missing manifest instead
Backpressure and resource limitsLow: rowless namespaces now consume the per-page namespace work budget.
Low: per-transaction memory now scales with staged entries.
Observability and diagnosabilityLow: the GC side pays back part of the writer-side saving, and the PR does not measure it.
Low: blob dependency checks run in caller order, not path-sorted order.
Checked and clean
Test gapEvery new test is unit-level and single-threaded. The invariant the PR actually rests on — a sweep A regression test in this repository's CAS suite would be the natural home: run an insert-heavy |
|
The CAS-36 sweep race happened in CI. It left a dangling ref after a successful Evidence
Sequence
Impact beyond the lost part
Why a923533 covers it
Not caused by #2614
CAS-36 spec §2.2 says this race fails closed at the final commit step. That is wrong: the sweep plans before the row exists and deletes after the commit. I will fix §2.2 and cite this run. |
PR #2528 CI VerificationVerdictNo regression. CI does not block approval. Four jobs failed. Every one is explained by something other than this PR: one Docker
Findings
|
| Ref | Occurrences (60 d) | Commits |
|---|---|---|
antalya-26.6 (branch) |
235 | 10 |
| PR 2528 | 61 | 2 |
| 20+ unrelated PRs and 2 release tags | 10–92 each | — |
Per-scenario rates confirm it. For six of the eight, the branch fails 21 of 66 runs
(32%) against 5 of 12 on this PR (42%) — the same rate within the noise of a
12-run sample. The seventh, SELECT WHERE parallel, is 3 of 66 on the branch
against 4 of 12 here, but it carries the identical mount-lease message, so it is the
same event reaching one more scenario rather than a separate failure.
The PR touches no lease, fence or mount-state code.
Regression cas_lightweight_delete_4 — pre-existing-flaky
One leaf scenario: /lightweight delete/concurrent delete/MergeTree/random delete half of the table without overlap counted 525 rows where it expected 500.
| Runs | Fails | Rate | |
|---|---|---|---|
antalya-26.6 |
55 | 4 | 7.3% |
| PR 2528 | 12 | 2 | 17% |
It also fails on PRs 2318, 2420, 2513, 2516, 2566 and 2567, and on release tag
v26.6.8.20001.altinityantalya. The server log contains no CAS error of any kind —
only Cancelled mutating parts and mutation failures, the ordinary shape of this
test racing concurrent deletes. Two failures in twelve runs is within what a 7%
baseline produces.
Stress test (amd_asan_ubsan, cas s3 storage) — pre-existing-flaky
Cannot start clickhouse-server: a Hybrid-engine table in test_5 fails to reattach
on restart because it names default.test_tiered_watermark_before (UNKNOWN_TABLE).
fatal.log is empty, so the server did not crash.
This test fails 10 of 10 branch runs in the last 60 days, and in 14 other PRs. It is
broken on antalya-26.6, not by this PR, which touches no table-loading or
Hybrid-engine code.
Cross-check against the code audit
The companion audit (PR-2528-AUDIT.md) flagged one Medium
hazard: promote no longer re-reads the manifest body, so a body deleted between
stageManifest and promote would commit a ref to a missing manifest, surfacing
later as FILE_DOESNT_EXIST.
Both CAS regression jobs were grepped for that symptom. Zero occurrences of
FILE_DOESNT_EXIST, manifest body absent or dangling across
cas_selects and cas_lightweight_delete_4 server logs. The hazard did not fire in
this run — which is expected, since its only named trigger is out of the protocol.
This is a negative result on two job-runs, not coverage. The audit's test gap stands:
nothing exercises a GC sweep round concurrently with a live stageManifest/promote.
Recommendation
Approve on CI grounds. Rerun the AST fuzzer job to clear the registry timeout if a
green board is wanted; the other three will not go green on a rerun and should not
block.
…romote' into perf/cas-avoid-manifest-get-on-promote Signed-off-by: Konstantin Morozov <just.morozov.k@gmail.com>
1'000 parts were inserted:
Changelog category (leave one):
Changelog entry (a user-readable short description of the changes that goes to CHANGELOG.md):
Reduced CAS object storage requests by reusing the proof recorded when a manifest is staged. Promotion no longer reads the manifest back, and cleanup deletes abandoned staged manifests using the recorded incarnation without a preliminary HEAD request.
Fixed a race between CAS manifest staging and orphan cleanup that could delete a committed manifest and leave a dangling reference.
Documentation entry for user-facing changes
...
CI/CD Options
Exclude tests:
Regression jobs to run: