Skip to content

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

Draft
filimonov wants to merge 4469 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 4469 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)
  • CAS (content-addressed storage; Antalya only)
  • 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 [5828352]


```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 25, 2026 07:27
Answers a review of rev.3, plus one owner correction that changes a decision.

Owner correction: once the migration window closes, an unprefixed CAS setting
name is REJECTED, not ignored. Silently discarding a value an operator wrote is
worse than refusing to start, and it left `blob_hash` -- fixed at pool creation,
unrecoverable afterwards -- protected by nothing but a log line. The design now
has no state in which a CAS setting value is silently dropped. The price is a
permanent reservation on twenty-five names inside a shared block, which the spec
states outright rather than implying an open namespace: unlike the defect being
fixed, that list is bounded, written down in three places, and a collision fails
loudly with a one-line remedy.

From the review: the aggregated warning is separated from the temporary
application of legacy values and appears in the loader sketch; the landing order
is fixed and made bisectable (Part 3 first, with a temporary `non_cas_keys`
entry, because the still-scanning loader would otherwise reject the key it just
moved -- and Part 2 hits the identical hazard, so it lands with Part 1); a key
repeated in either spelling is rejected via an explicit repeat-index split,
which Poco's `name[1]` rendering would otherwise let win silently; the state
table's pre-change row is corrected; the rollout text is corrected; the gate is
sized to the sweep, naming the stateless, integration, server-config and
`WriteBufferFromS3` lanes plus a new CAS-over-Azure smoke; and startup-failure
wording replaces "kills the server".

The window-closing task is filed in the operability backlog with its trigger.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Answers a review of rev.3, plus one owner correction that changes a decision.

Owner correction: once the migration window closes, an unprefixed CAS setting
name is REJECTED, not ignored. Silently discarding a value an operator wrote is
worse than refusing to start, and it left `blob_hash` -- fixed at pool creation,
unrecoverable afterwards -- protected by nothing but a log line. The design now
has no state in which a CAS setting value is silently dropped. The price is a
permanent reservation on twenty-five names inside a shared block, which the spec
states outright rather than implying an open namespace: unlike the defect being
fixed, that list is bounded, written down in three places, and a collision fails
loudly with a one-line remedy.

From the review: the aggregated warning is separated from the temporary
application of legacy values and appears in the loader sketch; the landing order
is fixed and made bisectable (Part 3 first, with a temporary `non_cas_keys`
entry, because the still-scanning loader would otherwise reject the key it just
moved -- and Part 2 hits the identical hazard, so it lands with Part 1); a key
repeated in either spelling is rejected via an explicit repeat-index split,
which Poco's `name[1]` rendering would otherwise let win silently; the state
table's pre-change row is corrected; the rollout text is corrected; the gate is
sized to the sweep, naming the stateless, integration, server-config and
`WriteBufferFromS3` lanes plus a new CAS-over-Azure smoke; and startup-failure
wording replaces "kills the server".

The window-closing task is filed in the operability backlog with its trigger.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Ten tasks. Task 1 moves the GCS conditional-PUT cap into the S3 settings and
must land first: it adds the key to `non_cas_keys` in the same commit, because
the still-scanning CAS loader would otherwise reject the key it just moved.
Task 2 is the namespace itself, the migration window and the `skip_access_check`
demotion, in one commit for the same bisectability reason. Tasks 3-7 are the
sweep, one commit per class, each with the lane that can actually see a miss --
the migration window is what makes them independently revertable. Task 8 adds a
CAS-over-Azure smoke, the case that proves the claim rather than restating it.
Task 9 is the full gate; Task 10 places the window-closing follow-up.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Two blockers, both confirmed against the code.

The CAS-over-Azure smoke could never have passed. A non-Local object storage
opens in Native mode, which requires enforced conditional operations; Azure
implements neither `removeObjectIfTokenMatches` nor the single-attempt retry
profile, and the base implementations refuse by design so the capability probe
fails closed. "The CAS parser accepts Azure keys" and "Azure can host a CAS
pool" are different claims and only the first is true. The spec now states that
boundary, and the plan proves the reachable claim end to end instead, on the
keys from the field report.

Four commit steps staged whole directories despite the plan's own exact-paths
rule; `utils/ca-soak` carries another session's edits and untracked run
artifacts, so they would have committed foreign changes. Every sweep task now
records its file list before editing and stages from that list, and the final
cleanliness check diffs against a baseline recorded before the first edit.

Also: the claim that the moved GCS cap had no unit seam was wrong -- the fake
S3 client fixture already builds a real S3ObjectStorage, four sites in it pass
the cap into the constructor Task 1 removes, and none of them asserts the cap is
enforced, so the plan converts all four and adds the missing test; the migration
warning is now asserted (one aggregated line, every legacy key, silence after a
full migration) via the log-capture pattern already used in the CAS tests; the
stateless selectors are derived from the recorded sweep list instead of a
hand-picked subset; the final sweep check covers all five classes rather than
XML alone; and the includes Task 2 needs are named.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
# Conflicts:
#	docs/superpowers/specs/2026-08-25-cas-disk-settings-namespace-design.md
`gcs_max_conditional_put_bytes` is a property of the GCS conditional-write
dialect, not a CAS policy: it takes effect only on a generation-token store,
and what CAS owns is the policy that such a write must not go multipart. That
policy is already a per-write flag. Only the number was in the wrong place.

The setting moves to `S3AuthSettings`, beside `gcs_issue_compose_request`,
keeping its config spelling, and `S3ObjectStorage` applies it itself when the
write carries the flag. `WriteSettings::s3_single_part_upload_max_bytes_override`
had exactly one producer and disappears with it.

The key is added to the CAS `non_cas_keys` skip-list in this commit so that the
still-scanning CAS loader keeps accepting it; the whole list is removed next.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
A CAS disk block is shared with the object storage, the generic disk layer and
the proxy resolver, and the CAS settings were the only consumer in it that
scanned every key and rejected whatever was not in a hand-written skip-list. Any
legal key nobody had enumerated failed server startup: all `s3_*` request
settings, most S3 client settings, repeated `<header>` elements, `<proxy>`, and
every Azure key, so a CAS disk over Azure could not be configured at all.

The CAS settings now live under a `cas_` config-key prefix and nothing else in
the block is read, so the skip-list is gone with nothing in its place. A
mis-spelled CAS setting is still rejected, because that check is now made over a
namespace CAS actually owns.

The unprefixed spelling is accepted for a bounded period, since configurations
using it already exist in external CI/CD scripts; each disk reports its
superseded keys once. A key written in both spellings, or twice in one spelling,
is rejected rather than resolved silently.

`skip_access_check` keeps its bare spelling and stops being a CAS setting: the
generic disk layer reads the same key, and one key must not become two.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Classify duplicate and ambiguous `cas_` settings before parsing values, logging
migration success, or changing the settings object. This keeps malformed values
from masking the required fail-closed exceptions.
Validate every owned `cas_` and legacy setting in a temporary settings state
before reporting migration success or changing the live configuration.
Run `loadFromConfig` post-processing and semantic validation on the temporary
CAS settings state before reporting migration success or replacing the live state.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
`http_keep_alive_timeout` in a CAS disk block used to fail server startup, which
is what blocked the mitigation suggested in #2243. The CAS
integration disk now carries that key and five more of the same class, so the
lane fails if the disk block ever stops accepting them.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Operator-facing XML snippets still advertised `server_root_id` and `blob_hash_allow_new` after CAS keys moved to the `cas_` namespace. Use `cas_server_root_id` and `cas_blob_hash_allow_new`, and pin the hash-admission exception in the pluggable-hash suite.
Report externally configured CAS settings with their `cas_*` names in validation, parser failures, staging capability checks, and mount-recovery guidance. Preserve the original prefixed spelling for unknown keys while keeping internal setting names and persisted fields unchanged.

Refresh stale integration comments to describe namespace ownership instead of the deleted `non_cas_keys` list.
(cherry picked from commit f76335f)
Signed-off-by: CarlosFelipeOR <carlosfelipeor@gmail.com>
(cherry picked from commit cc73c9b)
Signed-off-by: CarlosFelipeOR <carlosfelipeor@gmail.com>
(cherry picked from commit 3f288c1)
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