Skip to content

[WIP] CAS draft (adopting to CI/CD, not for review / merge) - #2073

Draft
filimonov wants to merge 4314 commits into
antalya-26.6from
cas-gc-rebuild
Draft

[WIP] CAS draft (adopting to CI/CD, not for review / merge)#2073
filimonov wants to merge 4314 commits into
antalya-26.6from
cas-gc-rebuild

Conversation

@filimonov

@filimonov filimonov commented Jul 17, 2026

Copy link
Copy Markdown
Member

Changelog category (leave one):

  • Not for changelog (changelog entry is not required)

Changelog entry (a user-readable short description of the changes that goes to CHANGELOG.md):

content addressable storage - draft PR

Documentation entry for user-facing changes

TBD.

Exclude tests:

  • Fast test
  • Integration Tests
  • Stateless tests
  • Stateful tests
  • Performance tests
  • Aarch64 tests
  • All with ASAN
  • All with TSAN
  • All with MSAN
  • All with UBSAN
  • All with Coverage
  • All Regression
  • Disable CI Cache

Regression jobs to run:

  • Fast suites (mostly <1h)
  • Aggregate Functions (2h)
  • Alter (1.5h)
  • Benchmark (30m)
  • ClickHouse Keeper (1h)
  • Iceberg (2h)
  • LDAP (1h)
  • OAuth (5m)
  • Parquet (1.5h)
  • RBAC (1.5h)
  • SSL Server (1h)
  • S3 (2h)
  • S3 Export (2h)
  • Swarms (30m)
  • Tiered Storage (2h)

@github-actions

github-actions Bot commented Jul 17, 2026

Copy link
Copy Markdown

Workflow [PR], commit [84c9492]


```sql
SYSTEM CONTENT ADDRESSED GC RUN [ON CLUSTER cluster_name] [disk_name]
```

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GC DISABLE ?

Comment thread ci/defs/job_configs.py Outdated
Comment thread ci/defs/job_configs.py Outdated
Comment thread ci/jobs/scripts/clickhouse_proc.py Outdated
filimonov and others added 30 commits August 21, 2026 22:01
…e has seven call sites)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HKgdqVjZwkpWPxLyHzduPb
Three things in the plan could not have worked as written.

Omitting the `PARTITION` clause builds the all-partitions command, which
reports itself as `UNFREEZE ALL`; the reference expected
`UNFREEZE PARTITION`. The clause is still omitted on purpose — it avoids
resolving a partition expression against a table whose live data was
dropped — so the reference follows the command that is actually built.

`SYSTEM CAS COLLECT GARBAGE` returns a result row with dynamic values, which
would have reached the test's stdout and broken the reference. Only its side
effect is wanted, so the output is suppressed.

The gtest snippet used two names that do not exist. `RootNamespace` exposes
its string through `string`, not a public `value`, and `serverRootId` is
already a public accessor, so the invented test-only one was unnecessary. The
plan had hedged with "if no such accessor exists, use the literal" — the
hedge is what should have been a grep.

The collection round also moves to a disk that is still live. It ran on the
disk whose only table had just been dropped, which works today only because
an inline disk survives in the registry after its table goes; the round folds
the whole pool, so starting it from the other disk covers the same namespaces
without depending on that.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VNBwsnT3qw4xAqk6SBCuFf
…a real gap), CAS-132 not-a-bug

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HKgdqVjZwkpWPxLyHzduPb
…ave verdicts

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HKgdqVjZwkpWPxLyHzduPb
…g, 87 overstated

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HKgdqVjZwkpWPxLyHzduPb
Three tasks: pin the cross-disk attach failure, give `freezeRemote` the same
single-transaction branch the other two clone paths already have, then fold
the corrections back into the adjudication.

The adjudicated fix shape was right in outline and short in three ways, so
the plan carries them itself rather than editing the spec: the post-clone
removals have to travel on the same transaction or they autocommit and
reintroduce the defect the transaction exists to prevent; the function's
`external_transaction` branches are byte-identical upstream code and only
look dead because this fork's single caller of that field goes elsewhere, so
they stay; and the helper the fix needs is declared after the function that
must call it, which no amount of reading the spec would have revealed.

The spec is not edited in place because another session is rewriting that
file right now. Task 3 lands the corrections once it is free, and refuses to
work around it if it is not.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VNBwsnT3qw4xAqk6SBCuFf
…brella review against HEAD

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HKgdqVjZwkpWPxLyHzduPb
Four documents need the fix recorded, and one of them is a code comment the
change outgrows: the copy helper justifies being sequential partly by "MOVE
is a background, latency-insensitive operation", and after this fix the same
helper also serves a user-issued attach. The correctness half of that
justification stands; only the latency clause stops covering all callers.

Two entries need more than a status flip. The same-pool verification item
asks whether the target's ref collides with the source's, and the new test
cannot answer it: that question is about `MOVE`, where both sides are one
table with one ref name, while `ATTACH` writes into the destination table's
namespace under a temporary name. The item must not be closed on the
strength of this test, so the plan says why in the item itself.

And the re-freeze-same-part-name item gets more reachable because of this
fix rather than less: its cross-disk route was closed by the very bug being
fixed here. Nothing in the fix is wrong; another item simply got easier to
hit, which is the kind of consequence a change does not announce about
itself.

The sweep's negative results are recorded too — the user-facing pages, the
same-disk path list, the already-closed move item, the replicated queue-clone
gap and one comment that stays true — so the next reader knows the check
happened and does not repeat it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VNBwsnT3qw4xAqk6SBCuFf
…open and untracked)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HKgdqVjZwkpWPxLyHzduPb
… review (Gc dtor UAF, claim() abort, disk() privilege bypass)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HKgdqVjZwkpWPxLyHzduPb
The green assertion could not have passed. `CASBlobBodyPutAvoided` is raised
only on the HEAD-first branch, that branch is taken above a threshold
defaulting to 1 MiB, and the test's blobs are a few bytes each — so the
counter would have read zero and the failure would have looked like the
dedup claim being false. The destination disk now lowers the threshold
explicitly. The earlier revision had deferred this to "the first run will
settle it", which was the wrong call twice over: the answer was derivable
from a default this session had already read, and a test that fails for an
unrelated reason teaches nothing.

The backlog task was inverted. That file declares itself a list of open work
with history left to git, and the comparable entry was deleted when its issue
was fixed rather than relabelled — so a fixed entry leaves the file instead
of gaining a FIXED heading. The plan also told the executor never to stage
that file and then staged it; the constraint is now about whose diff is in a
file, not about the file's name.

Retiring the entry turns out to need four coordinated edits in the triage
document, not one: the verdict row, the priority tally, the P1 table, and the
sentence beneath it. Three of four leaves a document that contradicts itself,
and the number left behind is the one someone reads to decide whether the
release is ready.

Two more gaps closed. The replicated attach reaches the same function through
different parameters — it is the one replicated clone site passing
`must_on_same_disk=false`, and its params set `metadata_version_to_write`, so
it repoints an already-committed part after the transaction commits. That
shape had no coverage; it has a leg now. And two source comments outside the
edited file become false: one claims a single transactional clone path, the
other lists the partition clone among paths still gated by their own checks.

Build and test steps now write to unique logs, build both binaries rather
than assuming the unit-test one is current, and read status from a marker
rather than a shell exit code.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VNBwsnT3qw4xAqk6SBCuFf
…ation work); backlog: M6, M8

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HKgdqVjZwkpWPxLyHzduPb
The site count was wrong: five, not four. The grep behind the earlier number
had been piped through `head`, and the site it hid is the largest one — a
whole triage section whose heading still ends "confirmed, P1" and whose body
says the fix is only scheduled. Four more lines in the same file reference
the backlog anchor being removed, and two of those assert things the fix
falsifies: that the branch is absent on HEAD, and that this path is the
family's one unclosed member.

The scheduling item moves into the same task as the deletion. It links the
anchor being removed, so leaving it in a later task would have left a
dangling link between two commits — an ordering fault, not a placement
preference.

Smaller repairs. The test's initial cleanup did not drop the tables its own
third leg creates, so an interrupted run could not be repeated. Exit markers
now sit on every build and every run rather than on two of five, since the
next line tells the reader to trust them. The reference file was described as
empty while actually holding a stale five-line version from an earlier draft,
which would have been appended to rather than replaced; it is emptied and
described accurately.

`set -euo pipefail` was considered and declined: about an eighth of the
stateless shell tests use it, and here it would abort at the leg that is
expected to fail before the fix, replacing an informative diff with a
truncated one. The instruction not to proceed is addressed to the
implementer, and the plan now says so instead of leaving it to be read as
script behaviour.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VNBwsnT3qw4xAqk6SBCuFf
…ccuracy, retry-later ProfileEvent

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HKgdqVjZwkpWPxLyHzduPb
…ce the review; two are 2031-triage duplicates)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HKgdqVjZwkpWPxLyHzduPb
…eview, nine untracked

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HKgdqVjZwkpWPxLyHzduPb
Three tasks: refuse an entry path that cannot survive the payload-zone
banner, stop one undecodable manifest from aborting every collection round,
then retire the entry and historicise the record.

Four things the adjudication does not say, and the first will surprise
whoever implements it. The encode-side check breaks two existing tests by
construction: the decode test reaches its assertion by encoding a malformed
path first, and the comment above it states the encoder's permissiveness as
deliberate. Both are repaired in the same task, and the decode check stays,
because manifest bytes also arrive from a peer that chose the path itself.

The error code is taken from the sibling check in the same function rather
than from first principles — duplicate paths are already refused there with
corrupted-data — and both new failure paths are reachable from ordinary DDL,
so neither is a logical error.

The sweep can only walk past the poison object, not delete it: proving an
orphan safe to delete needs the source edges the failing decode would have
produced. So it retains, records, and advances the cursor, trading one
visibly leaked object for a pool that keeps reclaiming. Fsck already reports
such an object as unaccounted, so it does not vanish.

The two halves also cannot be tested the same way. Once the encoder refuses
the path, the poison object can no longer be produced through DDL at all, so
the sweep's half plants bytes at the pool level through the shared sweep
fixture. And the stateless test asserts that nothing was left behind rather
than that the insert failed — it failed before the fix too, which is exactly
what a message-matching test would have missed.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VNBwsnT3qw4xAqk6SBCuFf
…ced createNamespaceStep1, decommission TOCTOU

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HKgdqVjZwkpWPxLyHzduPb
…d), only 1 of 42 items closed since the review

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HKgdqVjZwkpWPxLyHzduPb
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

antalya antalya-26.6 roadmap Key features and improvements for Antalya project

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants