meta: linearizable range-lease read on the admin transport (#223) - #233
Open
allamiro wants to merge 1 commit into
Open
meta: linearizable range-lease read on the admin transport (#223)#233allamiro wants to merge 1 commit into
allamiro wants to merge 1 commit into
Conversation
Second slice of #223. A candidate deciding whether to take a range has to be able to see whether the current lease is still live, and until now nothing could ask. The admin transport offered propose, status, and membership — no read of applied state at all. Without it the election loop could only guess: propose an acquisition, and learn from the rejection. That conflates two very different situations. A `GenerationMismatch` tells a candidate its CAS token was stale; it does not tell it whether the incumbent is healthy and renewing or dead and expired. Acting on that ambiguity is how a candidate fences a leader that was doing nothing wrong. `AdminReadRangeLease` returns the range's lease view together with the `range_generation` that acquisition must CAS against — reading the lease without the token it has to be paired with would leave the caller guessing again, one step further along. The read is linearizable, and the ordering is the point: `ensure_linearizable()` runs BEFORE the state is read. A deposed node serving its own lagging copy could report an expired lease that the real leader has already renewed, and a candidate acting on that answer would fence a perfectly healthy leader. Fencing first makes that impossible; a node that has lost leadership fails the read instead of answering it. Three distinctions the response keeps that a looser type would collapse: * a range that does not exist versus one that exists with nobody leading it; * an administrative lease with no deadline versus an election lease with one — the codec mirrors the durable presence-byte encoding from the previous slice so the two representations cannot drift apart in meaning; * the applied index the read was fenced at, so a caller can tell an answer from a newer state machine apart from a replayed older one. `OpenraftConsensus` gains an optional store handle. Optional because the existing harnesses build the façade from a bare Raft handle and have no applied state to offer; a read against one of those reports the store as unavailable rather than inventing an answer. `start_meta_node` attaches it, so every live node can serve reads. The openraft containment policy still holds: the new wire types and the trait are consensus-library-free, and the only openraft call sits inside `raft/`. Next slice: the node-side agent that uses this read to acquire and renew, and publishes grants into `MetaFencingEpoch`.
|
Bugbot is not enabled for your account, so this pull request was not reviewed. Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs. |
There was a problem hiding this comment.
1 issue found across 4 files
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="crates/vtop-meta/src/transport/wire.rs">
<violation number="1" location="crates/vtop-meta/src/transport/wire.rs:687">
P2: The new lease RPC types and kind IDs are not available through the transport API's established flat exports, making downstream implementations of the public admin surface inconsistent with the existing admin payloads. Re-export the new types/constants from `transport` (and the response types from the crate root where appropriate).</violation>
</file>
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
|
|
||
| /// Which range to read the lease for. | ||
| #[derive(Clone, Copy, Debug, PartialEq, Eq)] | ||
| pub struct AdminReadRangeLeaseRequest { |
There was a problem hiding this comment.
P2: The new lease RPC types and kind IDs are not available through the transport API's established flat exports, making downstream implementations of the public admin surface inconsistent with the existing admin payloads. Re-export the new types/constants from transport (and the response types from the crate root where appropriate).
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At crates/vtop-meta/src/transport/wire.rs, line 687:
<comment>The new lease RPC types and kind IDs are not available through the transport API's established flat exports, making downstream implementations of the public admin surface inconsistent with the existing admin payloads. Re-export the new types/constants from `transport` (and the response types from the crate root where appropriate).</comment>
<file context>
@@ -673,6 +682,123 @@ impl AdminStatusResponse {
+/// Which range to read the lease for.
+#[derive(Clone, Copy, Debug, PartialEq, Eq)]
+pub struct AdminReadRangeLeaseRequest {
+ pub topic_uuid: Uuid,
+ pub range_uuid: Uuid,
</file context>
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.
Second slice of #223, stacked on #232.
Why a candidate cannot decide without this
The admin transport offered propose, status, and membership — no read of applied state at all. So an election loop could only guess: propose an acquisition and learn from the rejection.
That conflates two very different situations. A
GenerationMismatchtells a candidate its CAS token was stale; it does not tell it whether the incumbent is healthy and renewing, or dead and expired. Acting on that ambiguity is exactly how a candidate fences a leader that was doing nothing wrong.AdminReadRangeLeasereturns the lease view together with therange_generationacquisition must CAS against — reading the lease without the token it has to be paired with would just move the guessing one step along.The ordering is the point
ensure_linearizable()runs before the state is read, not after. A deposed node serving its own lagging copy could report an expired lease that the real leader has already renewed, and a candidate acting on that would fence a healthy leader. Fencing first makes that impossible: a node that has lost leadership fails the read instead of answering it.Three distinctions the response keeps
Notes
OpenraftConsensusgains an optional store handle — optional because the existing harnesses build the façade from a bare Raft handle and have no applied state to offer; a read against one of those reports the store as unavailable rather than inventing an answer.start_meta_nodeattaches it.openraft containment holds: the new wire types and trait are consensus-library-free, and the only openraft call sits inside
raft/. The policy test passes.Refs #223.
Summary by cubic
Adds a linearizable range-lease read to the admin transport so candidates can see the current lease and CAS token before acquiring, preventing fences of a healthy leader. Supports #223.
read_range_leasethat fences with Raftensure_linearizable()before reading applied state.range_generation,fencing_epoch, optional lease view (admin vs election with expiry), andread_at_applied_index; distinguishes missing range from existing-without-lease.OpenraftConsensuscan be built with a store via.with_store(...);start_meta_nodeattaches it. Admin server and client gain new wire types and a client method to call the read; nodes without a store return an error instead of fabricating data.Written for commit 8bdb93c. Summary will update on new commits.