Repository navigation
Conversation
…ones run_cycle checked the publisher lease at the top of the cycle, then listed the spool, which hashes every staged pack, and re-checked the lease only before the second and later chunks. A lease quarantined during the listing still let the first chunk go up: up to indexer.max_packs packs that could only be owed in pending_index_, and that a crash with reconcile_on_start off orphans in the bucket. The check now runs before every chunk, the first included; it sends no request.
Contributor
There was a problem hiding this comment.
Copilot review overview
🔵 Needs a closer look
The newly detected lease loss is not propagated to catalog, allowing reconciliation to run without a lease.
Review effort: Balanced
Findings: None
What changed in this PR
Ensures every upload chunk receives a fresh publisher-lease check after spool listing.
Changes:
- Checks the lease before the first chunk.
- Adds a live regression test.
- Clarifies lease behavior documentation.
| File | Description |
|---|---|
native/csrc/catalog/storage_service.cpp |
Moves lease validation outside the later-chunk condition. |
native/csrc/catalog/storage_service.h |
Documents first-chunk validation timing. |
tests/test_native_capture_storage_live.py |
Tests lease loss during slow spool listing. |
💡 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.
Closes a gap in decision 7 (#150: no uploads while the service cannot index). The first chunk of every upload cycle went out without a fresh lease check.
What was wrong
run_cyclechecks the publisher lease at the top of the cycle (ensure_publisher_lease()), then callsspool_.ListPending, which hashes every staged pack. Over a backlog that takes seconds; it took about 1 s per GiB here. Before each chunk the loop re-checked the lease underLeaseScope, but only whennext != 0. The first chunk relied on the check made before the listing.The interleaving:
ListPendingstarts hashing the backlog.next == 0no check runs, andupload_chunkuploads up toindexer.max_packspacks (64 by default). The uploader then removes them from the spool.pending_index_. For the quarantine no cycle has the catalog, so those packs live only in memory. A crash withreconcile_on_start=Falseleaves them in the bucket and never in the catalog.That is the orphaning #150 forbids, and
storage_service.hclaimed the opposite ("A cycle checks the lease before each chunk it uploads").The fix
The
LeaseScope+writer_.held_lease()check now runs before every chunk, the first included, so it comes after the listing. It sends no request. The owed and cancel checks stay where they were, for later chunks only. The header comment now says the first chunk is checked after the listing.A lease lost while a chunk is in flight is still possible. That is the window the header already documents, at most one chunk.
Tests
test_a_lease_lost_while_the_spool_is_listed_uploads_nothingintests/test_native_capture_storage_live.py(manual, needs ClickHouse). It uses a sparse backlog of 64 × 128 MiB, which takes the listing about 8 s. The catalog is cut while the first cycle hashes, and the test asserts the lease quarantined before the listing ended. On main the cycle then uploads one pack: it fails withuploaded_packs == 1. With the fix it uploads nothing and every pack stays staged.cpu-goals:test_native_capture_storage_live.py,test_native_lease_request_bound.py,test_native_catalog_lease_live.py,test_native_capture_storage_wiring.pyand the spool, ownership, adoption and sink-release suites all pass.test_native_spool_adoption_live.py::test_a_flush_does_not_wait_for_an_adoption_to_list_a_dead_backlogtimed out once under load. It passed in isolation and in three full re-runs of its file, and its path doesn't go through the changed loop.pytest -m cpu: 2660 passed, 1 skipped.How it was found
The
PackPipelineTLA+ model on thespecs/formal-models-archivebranch found it (specs/tla/PackPipeline_firstchunk.cfgviolatesChunkStartsWithLease). The same check with the first chunk checked,PackPipeline_firstchunk_fixed.cfg, holds. The specs are not part of this PR.