Repository navigation
fetch: a request is answered only within its line; never older within it (#481) - #484
Merged
Merged
Conversation
…rrent installs in cache-interop (#481, #482) Tests only; the fixes follow in the next commits, so this head is expected to fail where the bindings are wrong. - genfixtures: four request-scope-* cases over a tree serving lines 26.3 and 26.8, each online: a higher line installed must not answer a lower line or an exact lower build; a newer build of the same line is kept for a line request (monotonic warning) but never answers an exact request for another version. - cache-interop: writer x reader x line (two lines in one cache, the lower added online), and N=8 concurrent installs into one fresh cache per binding and mixed, with a watcher for torn, vanished and replaced entries. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ed to it, install race-safely (#481, #482) #481, all four bindings, one rule (the lead's ruling): - The monotonic check keeps a newer install only when its signed version lies WITHIN the request: for a line request, a newer build of that line; for an exact request, a newer build of that exact version only. An install of another line never answers. The newest qualifying install is returned. Go (newerAlreadyInstalled) and TypeScript (checkMonotonic) compared every install for the platform; Python compared the same four-part version only, so it installed an older build of a line over a newer one. Rust already filtered by the request; it is unchanged. - A load-time assertion after every registry open: the library's own build_info clickhouse_version must be within the request, else CHTYPES_ARTIFACT_CORRUPT with reason build_info_mismatch:clickhouse_version (the code fetch-v1.md section 4 gives a signed version outside the request). A non-version tag is not checked. #482, all four bindings: - An unpacked entry is installed rename-first: an entry with an acceptable record is never removed or replaced; only one without is moved aside, and put back if it turns out good. TypeScript deleted the final entry and then renamed (raw ENOTEMPTY, vanished entries). Go, Python and Rust checked and then moved aside whatever stood there, which could be another process's complete install (measured for Go across processes on macOS, for Python across threads). - Listing reads only <manifest-hex> names, never an installer's temporary directory (Go, TypeScript, Rust; Python already did). - TypeScript: a filesystem failure in the fetch layer is a UsageError in the registry and the usage status in the CLI, as Go gives it. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…safe installs; CHANGELOGs (#481, #482) - fetch-v1.md section 9: a newer install is kept only within the request, and the load-time assertion (CHTYPES_ARTIFACT_CORRUPT, reason build_info_mismatch:clickhouse_version); section 1: how an unpacked entry is installed and what the interop job proves; section 10: the request-scope-* cases. - bindings-v1.md: the assertion in the artifact-corrupt row and as step 7 of the open sequence; the misuse row names the fetch layer's filesystem failure in Go and TypeScript. - One #481 and one #482 Fixed bullet, the same in all four CHANGELOGs. - Go race test: plain unpack dirs, no MkdirTemp (golangci usetesting). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ild is installed too (#481) The lead's ruling is "never answer a line request with a build older than one already installed within that line". All four bindings returned the offered build as soon as its manifest was installed, without the keep check, so with 26.3.4.1 and 26.3.9.1 both installed and the registry offering 26.3.4.1, an online `26.3` answered 26.3.4.1. Now the keep check runs on that path too (Go, TypeScript, Python: the already-installed branch; Rust: no longer skipped when `already`). Two conformance cases pin it: request-scope-newer-beside-offered (26.3 -> 26.3.9.1, monotonic warning) and request-scope-exact-beside-newer (26.3.4.1 -> 26.3.4.1). The first fails on the previous commit's Go. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
EricAndrechek
marked this pull request as ready for review
October 6, 2026 15:03
This was referenced Oct 6, 2026
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
A request is answered only within its own ClickHouse line, and the anti-rollback ("monotonic") keep is scoped to the request (#481). Concurrent installs into one cache no longer delete or replace each other's entries (#482). All four bindings follow one rule. There is no version bump.
#481: the scoped keep rule, in all four
26.3), that means any newer build of that line.26.3.38.2), only a newer build of that exact version.newerAlreadyInstalledand TypeScriptcheckMonotoniccompared the offer against every install for the platform. That is the wrong-line answer in Go and TypeScript can load the wrong ClickHouse line: a lower-line request is answered by a higher line already cached (measured, 1.0.2) #481.VersionRequest::matches.build_infoclickhouse_versionmust lie within the request. Otherwise the open fails asCHTYPES_ARTIFACT_CORRUPT, a loader refusal with reasonbuild_info_mismatch:clickhouse_version,wantthe request andgotthe version.fetch-v1.md§4 already makes "the signed version does not lie within the request"CHTYPES_ARTIFACT_CORRUPT, andbuild_info_mismatchis the existing loader refusal for abuild_infofield that disagrees. No new code, class or reason is added.open_unverifiedtakes no request, so it is out of scope.#482: race-safe installs, in all four
rm -rfon the final entry and then renamed.<manifest-hex>names, never an installer's temporary directory. Python already did this.UsageErrorin the registry, and the usage exit status in the CLI, as in Go.Tests
request-scope-*(6 cases × file/http), generated bygenfixtures, run in every binding'sv1-conformanceleg.v1-cache-interop, writer × reader × line. Each writer fetches 26.8. Each reader adds 26.3 online, then answers both lines offline.v1-cache-interop, concurrency. 8 processes at a time, for each binding alone and for all four mixed, 3 rounds each. A watcher reports torn, vanished and replaced entries.Evidence
936690f, run 37478628838.ts x8: 23/24 installed, REPLACED ×6, UNRECORDED ×1, VANISHED ×1.mixed x8: REPLACED ×4, TORN-LIBRARY ×1, VANISHED ×1.d11e58c(mergesmainat546489f): all 21 required contexts green,v1-parityandv1-cache-interopincluded (measured once every run on the commit had finished). The one failure is the report-onlysecurityscan, which fails onmaintoo.Test plan
go build/vet/test, golangci-lint;uv run pytest -q, ruff;tsc --noEmit(both configs), biome;cargo check/clippy/fmtgenfixtures --selftest/--check,schema_check.py,gen-constants --check,abi-v1/gen.py --check, lint-public/spelling/cited-paths/actions, dprint, markdownlint,policy-merge-check --check-guide/--selftestRelated issues
Fixes #481
Fixes #482
🤖 Generated with Claude Code