pub struct PlacementTable { /* private fields */ }Expand description
A concurrent, epoch-versioned map from partition to placement, carrying each
partition’s migration state machine (docs/06).
Cloneable handles are not provided here; wrap in an Arc to share. All
methods are non-blocking beyond a short critical section. Transitions are
total: an inapplicable transition returns a MigrationError and leaves the
table unchanged.
Implementations§
Source§impl PlacementTable
impl PlacementTable
Sourcepub fn set(&self, partition: PartitionId, placement: Placement) -> Epoch
pub fn set(&self, partition: PartitionId, placement: Placement) -> Epoch
Registers (or replaces) the placement for partition as Active,
stamping a fresh epoch and returning it. Initial registration; an
in-flight migration uses the phase transitions below, not set.
Sourcepub fn begin_migration(
&self,
partition: &PartitionId,
to: Placement,
) -> Result<Epoch, MigrationError>
pub fn begin_migration( &self, partition: &PartitionId, to: Placement, ) -> Result<Epoch, MigrationError>
Begins migrating partition to to: Active(from) → Migrating
Draining. Writes still go to from; the epoch advances.
§Errors
MigrationError::AlreadyMigrating if a migration is already in flight,
MigrationError::UnknownPartition if the partition has no placement.
Sourcepub fn enter_cutover(
&self,
partition: &PartitionId,
) -> Result<Epoch, MigrationError>
pub fn enter_cutover( &self, partition: &PartitionId, ) -> Result<Epoch, MigrationError>
Enters the cutover window: Draining → Cutover. Writes are now rejected
until complete_migration flips the pointer.
§Errors
MigrationError::NotMigrating if settled, MigrationError::NotDraining
if already past draining.
Sourcepub fn complete_migration(
&self,
partition: &PartitionId,
) -> Result<Epoch, MigrationError>
pub fn complete_migration( &self, partition: &PartitionId, ) -> Result<Epoch, MigrationError>
Completes the migration, the pointer flip: Cutover → Active(to).
§Errors
MigrationError::NotMigrating if settled, MigrationError::NotCutover
if not yet in cutover.
Sourcepub fn abort_migration(
&self,
partition: &PartitionId,
) -> Result<Epoch, MigrationError>
pub fn abort_migration( &self, partition: &PartitionId, ) -> Result<Epoch, MigrationError>
Aborts an in-flight migration, returning the partition to Active(from).
Since writes never committed to to (Draining wrote to from, Cutover
rejected), no rollback of data is needed (INV-M3).
§Errors
MigrationError::NotMigrating if the partition is settled.
Sourcepub fn state(&self, partition: &PartitionId) -> Option<(PartitionState, Epoch)>
pub fn state(&self, partition: &PartitionId) -> Option<(PartitionState, Epoch)>
The current migration state and the epoch it was stamped at, or None.
For observability and the control plane (docs/06 §5).
Sourcepub fn get(&self, partition: &PartitionId) -> Option<PlacementAt>
pub fn get(&self, partition: &PartitionId) -> Option<PlacementAt>
Resolves the placement reads go to (and its epoch), or None. The single
read placement, from until a migration completes, so a read never
sees a split view (INV-M4). The routing entry point.
Sourcepub fn admit_write(
&self,
partition: &PartitionId,
epoch: Epoch,
) -> WriteAdmission
pub fn admit_write( &self, partition: &PartitionId, epoch: Epoch, ) -> WriteAdmission
The migration write gate (docs/06 §2): may a write resolved at epoch
for partition commit now? WriteAdmission::Admit only if writes are
currently allowed (not in the Cutover window) and the partition’s
epoch is unchanged since the decision was resolved, otherwise
WriteAdmission::Reject, which the caller surfaces as a retryable
stale-epoch error so the client re-resolves and retries.
Epoch equality is the per-partition staleness check (epoch only advances
on this partition’s transitions), and the cutover gate handles the one
window where a write resolved at the current epoch must still be held:
together they give INV-M1 (no write in cutover) and INV-M2 (no write
against a superseded placement after the flip).
Sourcepub fn current_epoch(&self) -> Epoch
pub fn current_epoch(&self) -> Epoch
The current generation of the table (the epoch the most recent change
produced, or Epoch::ZERO if empty).