Skip to main content

ShardOwnershipCatalog

Struct ShardOwnershipCatalog 

Source
pub struct ShardOwnershipCatalog { /* private fields */ }
Expand description

The global shard ownership catalog held by every data member.

This single type plays both roles in ADR 0037’s model: it is the authoritative state the Cluster Supervisor leader writes through, and it is the replica each data member holds and routes against. Both write through apply_update, so the stale-version rejection that makes leader writes versioned is the same rule that makes replica application order-independent. Nothing here needs user-data sharding to find an entry: ranges are addressed directly by (collection, range_id), and routing (route) is a local scan of the replica.

Implementations§

Source§

impl ShardOwnershipCatalog

Source

pub fn plan_write_transaction( &self, targets: &[KeyTarget], ) -> Result<WriteTransactionPlan, WriteTransactionReject>

Plan a write transaction over targets in the first multi-writer cut (issue #1002).

Resolves every targeted key to its owning range and groups by writer:

Pure: it reads the catalog and returns intent. Each admitted write still passes admit_public_write at the owner’s current epoch, so a stale plan cannot smuggle a write past fencing.

Source

pub fn plan_read_fanout( &self, targets: &[KeyTarget], ) -> Result<ReadFanout, ReadFanoutReject>

Plan a simple, best-effort cross-range read fanout over targets (issue #1002).

Collects the resolved targets into one ReadLeg per owner so the caller can scatter the read across every range owner and gather the results. This is not a consistent snapshot — see ReadFanout. Err only when the read is empty or a target routes nowhere; spanning many owners is the expected, successful case.

Source

pub fn plan_consistent_read( &self, targets: &[KeyTarget], snapshot: Option<&GlobalReadWatermark>, ) -> Result<ConsistentReadPlan, ConsistentReadReject>

Plan a globally consistent cross-range read over targets, pinned to snapshot (issue #1002).

A consistent read must pin every range it touches to a single safe point:

This is the explicit safe-snapshot path: without it a cross-range read may only be served as a best-effort ReadFanout, never as a consistent one.

Source§

impl ShardOwnershipCatalog

Source

pub fn new() -> ShardOwnershipCatalog

An empty catalog — a cluster with no collections placed yet.

Source

pub fn declare_collection( &mut self, collection: CollectionId, mode: ShardKeyMode, ) -> Result<(), CatalogError>

Declare a collection’s shard key mode up front. Hash is the default, so this is mainly how an operator opts a collection into Ordered mode before any range exists. Declaring the same mode twice is idempotent; redeclaring a different mode for a collection that already has a mode is a ShardKeyModeMismatch.

Source

pub fn shard_key_mode(&self, collection: &CollectionId) -> Option<ShardKeyMode>

The declared shard key mode of collection, if it has any ranges or was explicitly declared.

Source

pub fn apply_update( &mut self, entry: RangeOwnership, ) -> Result<UpdateOutcome, CatalogError>

Apply a versioned ownership update — the single write path for both leader writes and replica application.

Creation (the range does not yet exist) auto-declares the collection’s mode from the entry and checks the new range does not overlap a sibling. Updating an existing range requires the entry’s version to strictly advance the current version; anything else is a StaleVersion rejection that leaves the catalog untouched. Either way the entry’s mode must match the collection’s declared mode.

Source

pub fn range( &self, collection: &CollectionId, range_id: RangeId, ) -> Option<&RangeOwnership>

The current ownership of one range, addressed directly by identity — no routing required, because the catalog is what routing is built on.

Source

pub fn ranges_for<'a>( &'a self, collection: &CollectionId, ) -> impl Iterator<Item = &'a RangeOwnership>

Every range of collection, in range-id order.

Source

pub fn route( &self, collection: &CollectionId, key: &[u8], ) -> Option<&RangeOwnership>

Route a normalized range key to the range that owns it — the catalog read every routing decision makes. Returns the owning RangeOwnership (whose owner, epoch, and replicas the caller uses to send and fence the write), or None if no range covers the key yet.

Source

pub fn route_shard_key( &self, collection: &CollectionId, shard_key: &[u8], ) -> Option<&RangeOwnership>

Route a logical shard key according to the collection’s declared mode.

Ordered collections route the shard key bytes directly. Hash collections first map the shard key into a stable hash slot and route that slot’s range key through the same collection -> range catalog.

Source

pub fn role_at( &self, node: &NodeIdentity, collection: &CollectionId, range_id: RangeId, ) -> Option<RangeRole>

This node’s RangeRole for a directly-addressed range (issue #990). Returns None when no such range exists in the catalog — distinct from NoCopy, which means the range exists but this node holds no copy of it.

Source

pub fn admit_public_write( &self, node: &NodeIdentity, collection: &CollectionId, key: &[u8], expected_epoch: OwnershipEpoch, ) -> Result<&RangeOwnership, RangeWriteReject>

Ownership-aware gate for a public write (issue #990, PRD #987).

Routes key to its range, then admits the write only when node is the range’s current Owner and expected_epoch matches the range’s current ownership epoch. On success returns the owned RangeOwnership (so the caller can proceed with the write against the authoritative epoch); otherwise a RangeWriteReject explaining why.

This is the public surface’s gate — the counterpart of the instance-wide WriteGate for multi-writer, per-range ownership. The internal replica-apply path does not consult it: replicated changes flow into a replica through the privileged apply path (fenced by issue #991’s range-authority watermark), so a node that rejects a public write here can still legitimately apply the owner’s replicated changes for the very same range.

Source

pub fn range_count(&self) -> usize

Total number of owned ranges across all collections.

Source

pub fn entries(&self) -> impl Iterator<Item = &RangeOwnership>

All ranges, in (collection, range_id) order — the full catalog content a joining member adopts as its starting replica (see ControlPlaneSnapshot).

Source§

impl ShardOwnershipCatalog

Source

pub fn plan_route( &self, local: &NodeIdentity, request: &RoutedRequest, policy: &RoutingPolicy, ) -> RouteDecision

Plan how local should handle request under policy — the any-node routing decision (issue #993).

Resolves the target range from the catalog, then:

  • owner of the range → Local;
  • non-owner, forwarding enabled, safe point op within budget → Forward to the owner;
  • non-owner but the op is unsafe to forward / oversized / forwarding disabled → Redirect with the owner+epoch hint;
  • no range covers the key → Unroutable.

The decision is pure: it reads the catalog and returns intent. Fencing is still enforced below routing — a forwarded or locally-executed write lands on admit_public_write at the owner’s current epoch, so a stale routing decision cannot smuggle a write past ownership.

Source§

impl ShardOwnershipCatalog

Source

pub fn topology_snapshot(&self) -> TopologySnapshot

Project the catalog into a driver-facing TopologySnapshot — the payload a topology poll serves (issue #994).

The snapshot carries every range’s bounds, owner, replicas, ownership epoch, and catalog version, and stamps a generation (version) drivers use to tell a newer snapshot from a stale one.

Trait Implementations§

Source§

impl Clone for ShardOwnershipCatalog

Source§

fn clone(&self) -> ShardOwnershipCatalog

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for ShardOwnershipCatalog

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
Source§

impl Default for ShardOwnershipCatalog

Source§

fn default() -> ShardOwnershipCatalog

Returns the “default value” for a type. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<'a, T, E> AsTaggedExplicit<'a, E> for T
where T: 'a,

Source§

fn explicit(self, class: Class, tag: u32) -> TaggedParser<'a, Explicit, Self, E>

Source§

impl<'a, T, E> AsTaggedImplicit<'a, E> for T
where T: 'a,

Source§

fn implicit( self, class: Class, constructed: bool, tag: u32, ) -> TaggedParser<'a, Implicit, Self, E>

Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> FromRef<T> for T
where T: Clone,

Source§

fn from_ref(input: &T) -> T

Converts to this type from a reference to the input type.
Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> IntoRequest<T> for T

Source§

fn into_request(self) -> Request<T>

Wrap the input message T in a tonic::Request
Source§

impl<L> LayerExt<L> for L

Source§

fn named_layer<S>(&self, service: S) -> Layered<<L as Layer<S>>::Service, S>
where L: Layer<S>,

Applies the layer to a service and wraps it in Layered.
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more