pub struct InMemoryLeaseCoordinator { /* private fields */ }Expand description
The honest in-process reference coordinator: a linearizable CAS register
behind Arc<Mutex> (genuinely linearizable within one process — the
mutex serializes every CAS), over an injected WallClock for
server-authoritative expiry. Clone shares the same register, so two device
handles contend over one linearizable cell — exactly the concurrency the
exclusivity/fencing tests exercise.
This cannot be backed by an eventually-consistent store. A synced-folder
/ FsRelay-style backend gives no consensus, so two sites could each “win”
the same acquire — the split-brain the whole design exists to prevent. The
distributed coordinator (Cosmos if_match, single-writer daemon, etc.) is
B6; it must supply real single-key linearizability, and this type is the
contract it implements.
Implementations§
Trait Implementations§
Source§impl Clone for InMemoryLeaseCoordinator
impl Clone for InMemoryLeaseCoordinator
Source§impl Debug for InMemoryLeaseCoordinator
impl Debug for InMemoryLeaseCoordinator
Source§impl LeaseCoordinator for InMemoryLeaseCoordinator
impl LeaseCoordinator for InMemoryLeaseCoordinator
Source§fn acquire(
&mut self,
agent_id: &str,
device_id: &str,
ttl_ms: u64,
) -> Result<Lease, LeaseError>
fn acquire( &mut self, agent_id: &str, device_id: &str, ttl_ms: u64, ) -> Result<Lease, LeaseError>
last_epoch + 1,
monotone, never reused) and expires_at_ms = now + ttl_ms. A
still-valid lease (held by anyone, including the caller) returns
LeaseError::Held — the holder keeps it alive with Self::renew.Source§fn renew(
&mut self,
agent_id: &str,
device_id: &str,
epoch: u64,
ttl_ms: u64,
) -> Result<Lease, LeaseError>
fn renew( &mut self, agent_id: &str, device_id: &str, epoch: u64, ttl_ms: u64, ) -> Result<Lease, LeaseError>
expires_at_ms without bumping the epoch. Ok iff
the caller is still the current holder at epoch (even slightly past
wall-clock expiry, as long as no one has stolen it — expiry only
enables stealing). Otherwise LeaseError::Lost.Source§fn release(
&mut self,
agent_id: &str,
device_id: &str,
epoch: u64,
) -> Result<(), LeaseError>
fn release( &mut self, agent_id: &str, device_id: &str, epoch: u64, ) -> Result<(), LeaseError>
epoch, drop the holder so the next acquire grants
immediately with the next epoch — no TTL wait. Otherwise
LeaseError::Lost. The epoch counter is retained across a release so
epochs never repeat.Source§fn current(&mut self, agent_id: &str) -> Result<Option<Lease>, LeaseError>
fn current(&mut self, agent_id: &str) -> Result<Option<Lease>, LeaseError>
epoch?” check reads this). None when the agent is
unheld (never acquired, or cleanly released). Note an expired but
un-stolen lease still reports its holder — expiry alone doesn’t clear
the register, only a steal or release does.