pub struct LeaseStore {
root: PathBuf,
ttl_ms: u64,
}Fields§
§root: PathBuf§ttl_ms: u64Implementations§
Source§impl LeaseStore
impl LeaseStore
Sourcepub fn open(registry_root: &Path) -> Result<Self>
pub fn open(registry_root: &Path) -> Result<Self>
<registry_root>/leases/. Creates the directory if missing.
fn content_path(&self, instance_id: &str) -> PathBuf
fn lock_path(&self, instance_id: &str) -> PathBuf
fn epoch_path(&self, instance_id: &str) -> PathBuf
fn read(path: &Path) -> Result<OnDisk>
Sourcefn next_epoch(&self, instance_id: &str, floor: u64) -> Result<u64>
fn next_epoch(&self, instance_id: &str, floor: u64) -> Result<u64>
Next ownership epoch for instance_id: one past the larger of the
persisted counter and floor (the current file’s epoch, which a lease
written before the counter existed may carry alone). Must be called
inside the key’s critical section.
Sourcepub fn claim(
&self,
instance_id: &str,
boot_id: &Arc<str>,
block_id: &str,
session_id_hint: Option<&str>,
) -> Result<Lease, LeaseError>
pub fn claim( &self, instance_id: &str, boot_id: &Arc<str>, block_id: &str, session_id_hint: Option<&str>, ) -> Result<Lease, LeaseError>
Attempt to claim the lease for instance_id. Kept for the
subprocess controller’s per-turn claim; see Self::claim_as.
Sourcepub fn claim_as(
&self,
instance_id: &str,
boot_id: &Arc<str>,
block_id: &str,
session_id_hint: Option<&str>,
info: &ClaimantInfo,
) -> Result<Lease, LeaseError>
pub fn claim_as( &self, instance_id: &str, boot_id: &Arc<str>, block_id: &str, session_id_hint: Option<&str>, info: &ClaimantInfo, ) -> Result<Lease, LeaseError>
Attempt to claim the lease for instance_id.
- Already held by
boot_id(this process) for the same block → idempotent re-claim, timestamp refreshed, epoch kept. - Held, not yet expired, by another block of this same process
→
Err(HeldByOther): one driver per agent holds inside a process too (ReAgent P1 on #3738), and the newcomer is the one refused. - Held by another owner, not yet expired, holder not provably
dead →
Err(HeldByOther). - Unreadable and rewritten within the TTL →
Err(HeldByOther)(fail closed — see module doc). - Free, expired, unreadable-and-stale, or held by a dead process → claimed under a new epoch.
The whole read-decide-write sequence runs inside a per-
instance_id exclusive lock (see module doc comment), so
there’s no window for a concurrent claimer to observe an
inconsistent state.
Sourcepub fn renew(&self, lease: &Lease) -> Result<(), LeaseError>
pub fn renew(&self, lease: &Lease) -> Result<(), LeaseError>
Extend a held lease’s TTL. Runs inside the same per-instance_id
critical section as claim, so the ownership check and the
write are atomic with respect to any concurrent claim/renew/
release for this instance — a caller that lost the lease to a
TTL reclaim between its last renew and this one gets a real
HeldByOther, never a silent clobber of the new owner’s file.
Sourcepub fn verify(&self, lease: &Lease) -> Result<(), LeaseError>
pub fn verify(&self, lease: &Lease) -> Result<(), LeaseError>
Is lease still ours? The pre-turn fence check: a holder that was
suspended past the TTL and reclaimed must find out before it starts
another turn, not only at its next renew tick. Does not write.
Sourcefn owned_file(&self, lease: &Lease) -> Result<LeaseFile, LeaseError>
fn owned_file(&self, lease: &Lease) -> Result<LeaseFile, LeaseError>
Read the lease file and confirm lease’s owner still holds it.
Caller holds the critical section.
Sourcepub fn release(&self, lease: &Lease) -> Result<(), LeaseError>
pub fn release(&self, lease: &Lease) -> Result<(), LeaseError>
Release a held lease. If it’s no longer ours — already
TTL-reclaimed by another process, or re-claimed by another block of
this same process — this is a safe no-op: deleting would destroy the
current holder’s lease, not ours. Idempotent: releasing an
already-missing lease is Ok(()). The epoch counter is never
removed (see module doc).
Sourcepub fn live_holder_other_than(
&self,
instance_id: &str,
own_boot_id: &str,
) -> Result<Option<LeaseHolder>>
pub fn live_holder_other_than( &self, instance_id: &str, own_boot_id: &str, ) -> Result<Option<LeaseHolder>>
The current holder of instance_id’s lease if it is live —
unexpired and not provably dead — and is not own_boot_id. The
read-only early check callers run before doing anything shared on
the agent’s behalf (spec I9); the binding decision is still claim.
An unreadable, still-fresh file is reported as held with an empty
holder (fail closed).
Auto Trait Implementations§
impl Freeze for LeaseStore
impl RefUnwindSafe for LeaseStore
impl Send for LeaseStore
impl Sync for LeaseStore
impl Unpin for LeaseStore
impl UnsafeUnpin for LeaseStore
impl UnwindSafe for LeaseStore
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can
then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be
further downcast into Rc<ConcreteType> where ConcreteType implements Trait.§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.§impl<T> DowncastSync for T
impl<T> DowncastSync for T
impl<A, B, T> HttpServerConnExec<A, B> for Twhere
B: Body,
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
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 moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
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