Repository navigation
Conversation
… live one adopt_step re-scanned the siblings on adoption_recheck_interval_ns only while its last scan had found a live one. A sibling claimed after that scan -- a rank or a restart that starts later than this service -- and then left with packs by a crash was never adopted while the service ran, and Spool's charge_dead_siblings kept charging it against the live sink's budget until the next restart on the node, contrary to spool.h's "the capacity comes back as adoption drains them". Rescan on the interval regardless. A pass lists the parent directory and probes each live sibling's lock without blocking, so the cost stays one directory listing per interval. live_siblings_ had no other reader and goes; the snapshot's live_siblings count is unchanged.
Contributor
There was a problem hiding this comment.
Copilot review overview
🟢 Approval recommended
The focused change addresses the liveness gap with targeted regression coverage and no unresolved blocking findings.
Review effort: Balanced
Findings: None
What changed in this PR
Fixes sibling-spool adoption so the storage service discovers directories created after an initial scan found no siblings.
Changes:
- Rechecks siblings periodically regardless of previous scan results.
- Removes unused tracking state and updates adoption comments.
- Adds regression coverage for a late-appearing sibling whose owner exits.
| File | Description |
|---|---|
| tests/test_native_spool_adoption_live.py | Tests adoption and catalog readback of a late sibling’s packs. |
| native/csrc/store/spool.h | Clarifies the budget-recovery comment. |
| native/csrc/catalog/storage_service.h | Updates interval documentation and removes obsolete state. |
| native/csrc/catalog/storage_service.cpp | Removes the live-sibling prerequisite for periodic scans. |
💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
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.
Fixes a liveness gap in #163's sibling-spool adoption. The gap matters for the planned multi-rank deployment, where each rank runs an upload-only service.
The defect
adopt_stepre-scanned the siblings onadoption_recheck_interval_nsonly while its last scan had found a live sibling (storage_service.cpp,recheck_due = live_siblings_ && ...). If the first scan found none, the service never looked again.A concrete scenario
live_siblings_is false.Spool'scharge_dead_siblingskeeps charging that directory against rank 0's sink budget. That contradictsspool.h's "the capacity comes back as adoption drains them".Today this needs a lease takeover to reach. With per-rank services, any rank that starts later than another and then crashes reaches it.
The fix
live_siblings_is removed. It had no other reader. The snapshot'slive_siblingscount is unchanged.spool.h's budget comment now match.How it was found
The
SpoolOwnershipTLA+ model onspecs/formal-models-archivefound it.SpoolOwnership_live_takeoverand_live_multiviolate adoption liveness._live_fix,_live_multi_fixand_charge_fixhold once the recheck is unconditional. Nospecs/files are added here.Tests
New test:
test_a_sibling_that_appears_after_start_and_dies_is_adoptedintests/test_native_spool_adoption_live.py. The service's first look finds no sibling. A sibling is then claimed, staged into with the real native pack sink, and released. The test expects it to be adopted, removed, and read back from the catalog.Suites run, against local ClickHouse 25.12 and the fake S3 fixture, with no GPU:
tests/test_native_spool_adoption_live.pytest_native_spool{,_ownership,_owner_lock,_owner_lock_unit,_reservations}.pytest_native_capture_storage_live.pytest_native_capture_storage_wiring.pytest_native_live_spool.pytest_native_sink_release.pytest_native_lease_request_bound.pyAll pass, with the sink, store and conformance drivers built.