Skip to main content

ProcessRegistry

Trait ProcessRegistry 

Source
pub trait ProcessRegistry: Send + Sync {
Show 34 methods // Required methods fn register_process<'life0, 'async_trait>( &'life0 self, registration: ProcessRegistration, ) -> Pin<Box<dyn Future<Output = Result<ProcessRecord, PluginError>> + Send + 'async_trait>> where 'life0: 'async_trait, Self: 'async_trait; fn set_external_ref<'life0, 'life1, 'async_trait>( &'life0 self, process_id: &'life1 str, external_ref: ProcessExternalRef, ) -> Pin<Box<dyn Future<Output = Result<ProcessRecord, PluginError>> + Send + 'async_trait>> where 'life0: 'async_trait, 'life1: 'async_trait, Self: 'async_trait; fn grant_handle<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, session_scope: &'life1 SessionScope, process_id: &'life2 str, descriptor: ProcessHandleDescriptor, ) -> Pin<Box<dyn Future<Output = Result<ProcessHandleGrant, PluginError>> + Send + 'async_trait>> where 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, Self: 'async_trait; fn revoke_handle<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, session_scope: &'life1 SessionScope, process_id: &'life2 str, ) -> Pin<Box<dyn Future<Output = Result<(), PluginError>> + Send + 'async_trait>> where 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, Self: 'async_trait; fn transfer_handle_grants<'life0, 'life1, 'life2, 'life3, 'async_trait>( &'life0 self, from_scope: &'life1 SessionScope, to_scope: &'life2 SessionScope, process_ids: &'life3 [String], ) -> Pin<Box<dyn Future<Output = Result<(), PluginError>> + Send + 'async_trait>> where 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, 'life3: 'async_trait, Self: 'async_trait; fn list_handle_grants<'life0, 'life1, 'async_trait>( &'life0 self, session_scope: &'life1 SessionScope, ) -> Pin<Box<dyn Future<Output = Result<Vec<(ProcessHandleGrant, ProcessRecord)>, PluginError>> + Send + 'async_trait>> where 'life0: 'async_trait, 'life1: 'async_trait, Self: 'async_trait; fn handle_grants_for_process<'life0, 'life1, 'async_trait>( &'life0 self, process_id: &'life1 str, ) -> Pin<Box<dyn Future<Output = Result<Vec<ProcessHandleGrant>, PluginError>> + Send + 'async_trait>> where 'life0: 'async_trait, 'life1: 'async_trait, Self: 'async_trait; fn delete_session_process_state<'life0, 'life1, 'async_trait>( &'life0 self, session_id: &'life1 str, ) -> Pin<Box<dyn Future<Output = Result<ProcessSessionDeleteReport, PluginError>> + Send + 'async_trait>> where 'life0: 'async_trait, 'life1: 'async_trait, Self: 'async_trait; fn append_event<'life0, 'life1, 'async_trait>( &'life0 self, process_id: &'life1 str, request: ProcessEventAppendRequest, ) -> Pin<Box<dyn Future<Output = Result<ProcessEventAppendResult, PluginError>> + Send + 'async_trait>> where 'life0: 'async_trait, 'life1: 'async_trait, Self: 'async_trait; fn events_after<'life0, 'life1, 'async_trait>( &'life0 self, process_id: &'life1 str, after_sequence: u64, ) -> Pin<Box<dyn Future<Output = Result<Vec<ProcessEvent>, PluginError>> + Send + 'async_trait>> where 'life0: 'async_trait, 'life1: 'async_trait, Self: 'async_trait; fn wake_events_after<'life0, 'life1, 'async_trait>( &'life0 self, process_id: &'life1 str, after_sequence: u64, ) -> Pin<Box<dyn Future<Output = Result<Vec<ProcessEvent>, PluginError>> + Send + 'async_trait>> where 'life0: 'async_trait, 'life1: 'async_trait, Self: 'async_trait; fn complete_process<'life0, 'life1, 'async_trait>( &'life0 self, process_id: &'life1 str, await_output: ProcessAwaitOutput, authority: ProcessCompletionAuthority, ) -> Pin<Box<dyn Future<Output = Result<ProcessRecord, PluginError>> + Send + 'async_trait>> where 'life0: 'async_trait, 'life1: 'async_trait, Self: 'async_trait; fn complete_process_with_lease<'life0, 'life1, 'async_trait>( &'life0 self, lease: &'life1 ProcessLease, await_output: ProcessAwaitOutput, ) -> Pin<Box<dyn Future<Output = Result<ProcessRecord, PluginError>> + Send + 'async_trait>> where 'life0: 'async_trait, 'life1: 'async_trait, Self: 'async_trait; fn record_first_started<'life0, 'life1, 'async_trait>( &'life0 self, process_id: &'life1 str, started: ProcessStarted, ) -> Pin<Box<dyn Future<Output = Result<ProcessRecord, PluginError>> + Send + 'async_trait>> where 'life0: 'async_trait, 'life1: 'async_trait, Self: 'async_trait; fn request_process_abandon<'life0, 'life1, 'async_trait>( &'life0 self, process_id: &'life1 str, request: AbandonRequest, ) -> Pin<Box<dyn Future<Output = Result<ProcessRecord, PluginError>> + Send + 'async_trait>> where 'life0: 'async_trait, 'life1: 'async_trait, Self: 'async_trait; fn set_process_wait<'life0, 'life1, 'async_trait>( &'life0 self, process_id: &'life1 str, wait: WaitState, ) -> Pin<Box<dyn Future<Output = Result<ProcessRecord, PluginError>> + Send + 'async_trait>> where 'life0: 'async_trait, 'life1: 'async_trait, Self: 'async_trait; fn clear_process_wait<'life0, 'life1, 'async_trait>( &'life0 self, process_id: &'life1 str, ) -> Pin<Box<dyn Future<Output = Result<ProcessRecord, PluginError>> + Send + 'async_trait>> where 'life0: 'async_trait, 'life1: 'async_trait, Self: 'async_trait; fn get_process<'life0, 'life1, 'async_trait>( &'life0 self, process_id: &'life1 str, ) -> Pin<Box<dyn Future<Output = Option<ProcessRecord>> + Send + 'async_trait>> where 'life0: 'async_trait, 'life1: 'async_trait, Self: 'async_trait; fn list_processes<'life0, 'life1, 'async_trait>( &'life0 self, filter: &'life1 ProcessListFilter, ) -> Pin<Box<dyn Future<Output = Result<Vec<ProcessRecord>, PluginError>> + Send + 'async_trait>> where 'life0: 'async_trait, 'life1: 'async_trait, Self: 'async_trait; fn processes_changed_since<'life0, 'async_trait>( &'life0 self, cursor: ProcessChangeCursor, limit: usize, ) -> Pin<Box<dyn Future<Output = Result<(Vec<ProcessRecord>, ProcessChangeCursor), PluginError>> + Send + 'async_trait>> where 'life0: 'async_trait, Self: 'async_trait; fn ack_wake<'life0, 'life1, 'async_trait>( &'life0 self, process_id: &'life1 str, sequence: u64, ) -> Pin<Box<dyn Future<Output = Result<(), PluginError>> + Send + 'async_trait>> where 'life0: 'async_trait, 'life1: 'async_trait, Self: 'async_trait; fn list_non_terminal<'life0, 'async_trait>( &'life0 self, ) -> Pin<Box<dyn Future<Output = Result<Vec<ProcessRecord>, PluginError>> + Send + 'async_trait>> where 'life0: 'async_trait, Self: 'async_trait; fn live_reference_summary<'life0, 'async_trait>( &'life0 self, ) -> Pin<Box<dyn Future<Output = Result<Vec<ProcessLiveReferenceSummary>, PluginError>> + Send + 'async_trait>> where 'life0: 'async_trait, Self: 'async_trait; fn claim_process_lease<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, process_id: &'life1 str, owner: &'life2 LeaseOwnerIdentity, lease_ttl_ms: u64, ) -> Pin<Box<dyn Future<Output = Result<ProcessLeaseClaimOutcome, PluginError>> + Send + 'async_trait>> where 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, Self: 'async_trait; fn reclaim_process_lease<'life0, 'life1, 'life2, 'life3, 'async_trait>( &'life0 self, process_id: &'life1 str, owner: &'life2 LeaseOwnerIdentity, observed_holder: &'life3 ProcessLease, lease_ttl_ms: u64, ) -> Pin<Box<dyn Future<Output = Result<ProcessLeaseClaimOutcome, PluginError>> + Send + 'async_trait>> where 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, 'life3: 'async_trait, Self: 'async_trait; fn renew_process_lease<'life0, 'life1, 'async_trait>( &'life0 self, lease: &'life1 ProcessLease, lease_ttl_ms: u64, ) -> Pin<Box<dyn Future<Output = Result<ProcessLease, PluginError>> + Send + 'async_trait>> where 'life0: 'async_trait, 'life1: 'async_trait, Self: 'async_trait; fn get_process_lease<'life0, 'life1, 'async_trait>( &'life0 self, process_id: &'life1 str, ) -> Pin<Box<dyn Future<Output = Result<Option<ProcessLease>, PluginError>> + Send + 'async_trait>> where 'life0: 'async_trait, 'life1: 'async_trait, Self: 'async_trait; fn complete_process_lease<'life0, 'life1, 'async_trait>( &'life0 self, completion: &'life1 ProcessLeaseCompletion, ) -> Pin<Box<dyn Future<Output = Result<(), PluginError>> + Send + 'async_trait>> where 'life0: 'async_trait, 'life1: 'async_trait, Self: 'async_trait; fn prune_terminal_processes<'life0, 'async_trait>( &'life0 self, cutoff_epoch_ms: u64, filter: Option<ProcessListFilter>, up_to_change_seq: Option<ProcessChangeCursor>, ) -> Pin<Box<dyn Future<Output = Result<ProcessPruneReport, PluginError>> + Send + 'async_trait>> where 'life0: 'async_trait, Self: 'async_trait; // Provided methods fn durability_tier(&self) -> DurabilityTier { ... } fn list_live_handle_grants<'life0, 'life1, 'async_trait>( &'life0 self, session_scope: &'life1 SessionScope, ) -> Pin<Box<dyn Future<Output = Result<Vec<(ProcessHandleGrant, ProcessRecord)>, PluginError>> + Send + 'async_trait>> where 'life0: 'async_trait, 'life1: 'async_trait, Self: 'async_trait { ... } fn has_handle_grant<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, session_scope: &'life1 SessionScope, process_id: &'life2 str, ) -> Pin<Box<dyn Future<Output = Result<bool, PluginError>> + Send + 'async_trait>> where 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, Self: 'async_trait { ... } fn count_events_through<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, process_id: &'life1 str, event_type: &'life2 str, up_to_sequence: u64, ) -> Pin<Box<dyn Future<Output = Result<u64, PluginError>> + Send + 'async_trait>> where 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, Self: 'async_trait { ... } fn recent_events<'life0, 'life1, 'async_trait>( &'life0 self, process_id: &'life1 str, limit: usize, ) -> Pin<Box<dyn Future<Output = Result<Vec<ProcessEvent>, PluginError>> + Send + 'async_trait>> where 'life0: 'async_trait, 'life1: 'async_trait, Self: 'async_trait { ... }
}
Expand description

Durability-neutral process registry.

Process waits are coordination behavior and live on ProcessWorkDriver / ProcessAwaiter, not on persistence implementations. Registry methods are point reads and writes only. See docs/adr/0016-process-waits-live-on-the-work-driver-seam.md.

Required Methods§

Source

fn register_process<'life0, 'async_trait>( &'life0 self, registration: ProcessRegistration, ) -> Pin<Box<dyn Future<Output = Result<ProcessRecord, PluginError>> + Send + 'async_trait>>
where 'life0: 'async_trait, Self: 'async_trait,

Source

fn set_external_ref<'life0, 'life1, 'async_trait>( &'life0 self, process_id: &'life1 str, external_ref: ProcessExternalRef, ) -> Pin<Box<dyn Future<Output = Result<ProcessRecord, PluginError>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, Self: 'async_trait,

Attach a durable backend reference to a registered process.

Implementations must reject unknown process ids. The first assignment stores the reference. Repeating the exact same assignment is an idempotent no-op that returns the existing record unchanged. Assigning a different reference after one has been stored is a registry model error.

Source

fn grant_handle<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, session_scope: &'life1 SessionScope, process_id: &'life2 str, descriptor: ProcessHandleDescriptor, ) -> Pin<Box<dyn Future<Output = Result<ProcessHandleGrant, PluginError>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, Self: 'async_trait,

Source

fn revoke_handle<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, session_scope: &'life1 SessionScope, process_id: &'life2 str, ) -> Pin<Box<dyn Future<Output = Result<(), PluginError>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, Self: 'async_trait,

Source

fn transfer_handle_grants<'life0, 'life1, 'life2, 'life3, 'async_trait>( &'life0 self, from_scope: &'life1 SessionScope, to_scope: &'life2 SessionScope, process_ids: &'life3 [String], ) -> Pin<Box<dyn Future<Output = Result<(), PluginError>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, 'life3: 'async_trait, Self: 'async_trait,

Source

fn list_handle_grants<'life0, 'life1, 'async_trait>( &'life0 self, session_scope: &'life1 SessionScope, ) -> Pin<Box<dyn Future<Output = Result<Vec<(ProcessHandleGrant, ProcessRecord)>, PluginError>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, Self: 'async_trait,

Source

fn handle_grants_for_process<'life0, 'life1, 'async_trait>( &'life0 self, process_id: &'life1 str, ) -> Pin<Box<dyn Future<Output = Result<Vec<ProcessHandleGrant>, PluginError>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, Self: 'async_trait,

Source

fn delete_session_process_state<'life0, 'life1, 'async_trait>( &'life0 self, session_id: &'life1 str, ) -> Pin<Box<dyn Future<Output = Result<ProcessSessionDeleteReport, PluginError>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, Self: 'async_trait,

Source

fn append_event<'life0, 'life1, 'async_trait>( &'life0 self, process_id: &'life1 str, request: ProcessEventAppendRequest, ) -> Pin<Box<dyn Future<Output = Result<ProcessEventAppendResult, PluginError>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, Self: 'async_trait,

Source

fn events_after<'life0, 'life1, 'async_trait>( &'life0 self, process_id: &'life1 str, after_sequence: u64, ) -> Pin<Box<dyn Future<Output = Result<Vec<ProcessEvent>, PluginError>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, Self: 'async_trait,

Source

fn wake_events_after<'life0, 'life1, 'async_trait>( &'life0 self, process_id: &'life1 str, after_sequence: u64, ) -> Pin<Box<dyn Future<Output = Result<Vec<ProcessEvent>, PluginError>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, Self: 'async_trait,

Source

fn complete_process<'life0, 'life1, 'async_trait>( &'life0 self, process_id: &'life1 str, await_output: ProcessAwaitOutput, authority: ProcessCompletionAuthority, ) -> Pin<Box<dyn Future<Output = Result<ProcessRecord, PluginError>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, Self: 'async_trait,

Complete a process without a Lash process lease, under an explicit, auditable completion authority.

This path is reserved for writers whose single-writer discipline lives outside the Lash lease: an external actor closing an externally-owned row, a workflow-key-coalesced substrate completing a row it ran, or the sweep reconciling an abandon request. The ProcessCompletionAuthority names which of these applies; the implementation MUST call authority.validate against the row’s declared RecoveryDisposition inside this operation, so a mismatched authority is rejected with a typed error before any terminal event is appended, and MUST record the authority on the terminal event as audit evidence (via terminal_append_request).

Lash-owned workers must instead use complete_process_with_lease, which fences the terminal append and lease release in one atomic operation.

Source

fn complete_process_with_lease<'life0, 'life1, 'async_trait>( &'life0 self, lease: &'life1 ProcessLease, await_output: ProcessAwaitOutput, ) -> Pin<Box<dyn Future<Output = Result<ProcessRecord, PluginError>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, Self: 'async_trait,

Atomically append the terminal output while the supplied process lease is still current, then release that lease in the same transaction.

Implementations must validate owner incarnation, lease token, fencing token, and expiry against the persisted lease. A stale or expired writer is rejected without appending any terminal event or clearing a newer owner’s lease. Replaying the same terminal event after a successful completion returns the existing terminal record.

Source

fn record_first_started<'life0, 'life1, 'async_trait>( &'life0 self, process_id: &'life1 str, started: ProcessStarted, ) -> Pin<Box<dyn Future<Output = Result<ProcessRecord, PluginError>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, Self: 'async_trait,

Record the durable, lease-fenced “execution started” fact (ADR 0019).

First-writer-wins: the first call stores started; a later call is an idempotent no-op returning the existing record unchanged (the fact is immutable once written, so the sweep can prove an OwnerBound row has begun executing). Implementations reject unknown process ids.

Source

fn request_process_abandon<'life0, 'life1, 'async_trait>( &'life0 self, process_id: &'life1 str, request: AbandonRequest, ) -> Pin<Box<dyn Future<Output = Result<ProcessRecord, PluginError>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, Self: 'async_trait,

Set the durable, non-terminal Abandon Request marker (ADR 0019).

First-writer-wins: if a marker is already present the call is an idempotent no-op returning the existing record unchanged, preserving the original recorded authorization rather than letting a later requester clobber it. Setting it on a terminal row is a model error — a terminal process has already recorded its outcome, so there is nothing to abandon.

Source

fn set_process_wait<'life0, 'life1, 'async_trait>( &'life0 self, process_id: &'life1 str, wait: WaitState, ) -> Pin<Box<dyn Future<Output = Result<ProcessRecord, PluginError>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, Self: 'async_trait,

Source

fn clear_process_wait<'life0, 'life1, 'async_trait>( &'life0 self, process_id: &'life1 str, ) -> Pin<Box<dyn Future<Output = Result<ProcessRecord, PluginError>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, Self: 'async_trait,

Source

fn get_process<'life0, 'life1, 'async_trait>( &'life0 self, process_id: &'life1 str, ) -> Pin<Box<dyn Future<Output = Option<ProcessRecord>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, Self: 'async_trait,

Source

fn list_processes<'life0, 'life1, 'async_trait>( &'life0 self, filter: &'life1 ProcessListFilter, ) -> Pin<Box<dyn Future<Output = Result<Vec<ProcessRecord>, PluginError>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, Self: 'async_trait,

Source

fn processes_changed_since<'life0, 'async_trait>( &'life0 self, cursor: ProcessChangeCursor, limit: usize, ) -> Pin<Box<dyn Future<Output = Result<(Vec<ProcessRecord>, ProcessChangeCursor), PluginError>> + Send + 'async_trait>>
where 'life0: 'async_trait, Self: 'async_trait,

Return process records whose persisted row changed strictly after cursor, ordered by the backend’s per-store change sequence.

This is a host-level completeness read for trusted projectors. It is not scoped by handle grants, and the cursor must be treated as opaque outside the store that issued it.

Source

fn ack_wake<'life0, 'life1, 'async_trait>( &'life0 self, process_id: &'life1 str, sequence: u64, ) -> Pin<Box<dyn Future<Output = Result<(), PluginError>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, Self: 'async_trait,

Source

fn list_non_terminal<'life0, 'async_trait>( &'life0 self, ) -> Pin<Box<dyn Future<Output = Result<Vec<ProcessRecord>, PluginError>> + Send + 'async_trait>>
where 'life0: 'async_trait, Self: 'async_trait,

All non-terminal process records, in stable process_id order.

This is the recovery sweep’s worklist: every process that was started but has not reached a terminal event is a candidate for re-execution by a DurableProcessWorker after a crash. Terminal processes are excluded — they are already done and idempotent by process_id, so re-running them would be wasted work.

Source

fn live_reference_summary<'life0, 'async_trait>( &'life0 self, ) -> Pin<Box<dyn Future<Output = Result<Vec<ProcessLiveReferenceSummary>, PluginError>> + Send + 'async_trait>>
where 'life0: 'async_trait, Self: 'async_trait,

Count non-terminal process rows by their captured definition and execution-environment references.

Source

fn claim_process_lease<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, process_id: &'life1 str, owner: &'life2 LeaseOwnerIdentity, lease_ttl_ms: u64, ) -> Pin<Box<dyn Future<Output = Result<ProcessLeaseClaimOutcome, PluginError>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, Self: 'async_trait,

Claim the durable single-owner lease over a non-terminal process.

An unexpired lease held by a different owner returns ProcessLeaseClaimOutcome::Busy carrying the observed holder; claiming a free or expired lease succeeds and bumps the fencing_token, and the same incarnation re-entering its own live lease extends it without changing token or fence. The returned ProcessLease’s (owner, lease_token) plus fencing_token are the contract a worker presents on every subsequent renew/complete — a stale writer is rejected.

Source

fn reclaim_process_lease<'life0, 'life1, 'life2, 'life3, 'async_trait>( &'life0 self, process_id: &'life1 str, owner: &'life2 LeaseOwnerIdentity, observed_holder: &'life3 ProcessLease, lease_ttl_ms: u64, ) -> Pin<Box<dyn Future<Output = Result<ProcessLeaseClaimOutcome, PluginError>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, 'life3: 'async_trait, Self: 'async_trait,

Reclaim an unexpired process lease whose observed holder is definitely dead according to persisted local-process liveness metadata.

Mirrors RuntimePersistence::reclaim_session_execution_lease: backends must CAS on observed_holder (owner identity, lease token, and fencing token) so a stale claimant cannot clear a newer live lease that won the race after the busy observation, and a successful reclaim must advance the fencing token monotonically.

Source

fn renew_process_lease<'life0, 'life1, 'async_trait>( &'life0 self, lease: &'life1 ProcessLease, lease_ttl_ms: u64, ) -> Pin<Box<dyn Future<Output = Result<ProcessLease, PluginError>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, Self: 'async_trait,

Extend the expiry of a live lease the caller still owns.

The lease must match the persisted (owner, lease_token, fencing_token) and be unexpired, else the renewal is rejected (the lease was superseded or expired). Workers renew across long-running effects so a healthy process is not swept out from under its live owner.

Source

fn get_process_lease<'life0, 'life1, 'async_trait>( &'life0 self, process_id: &'life1 str, ) -> Pin<Box<dyn Future<Output = Result<Option<ProcessLease>, PluginError>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, Self: 'async_trait,

Read the current lease row for a process without claiming it.

Returns the persisted lease when one is held (owner and token present), or None when the row is unleased or released. The returned lease may be expired: expiry is a raw fact exposed read-side (ADR 0019) so hosts classify staleness themselves; this never mutates the lease. Unknown process ids return None.

Source

fn complete_process_lease<'life0, 'life1, 'async_trait>( &'life0 self, completion: &'life1 ProcessLeaseCompletion, ) -> Pin<Box<dyn Future<Output = Result<(), PluginError>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, Self: 'async_trait,

Release a lease the caller owns, fenced by the completion’s (process_id, lease_token).

Mirrors clearing a runtime turn lease: a stale completion (whose token no longer matches the live lease) is a no-op so it cannot release a lease a newer owner now holds. Idempotent — completing an already-released lease succeeds.

Source

fn prune_terminal_processes<'life0, 'async_trait>( &'life0 self, cutoff_epoch_ms: u64, filter: Option<ProcessListFilter>, up_to_change_seq: Option<ProcessChangeCursor>, ) -> Pin<Box<dyn Future<Output = Result<ProcessPruneReport, PluginError>> + Send + 'async_trait>>
where 'life0: 'async_trait, Self: 'async_trait,

Physically delete terminal process rows whose updated_at_ms is older than cutoff_epoch_ms, match filter when one is supplied, and have a process change sequence no later than up_to_change_seq when supplied, together with their events, wake acks, handle grants, lease rows, and trigger-delivery reservations whose deterministic process id points at a pruned row. Host-scheduled retention: hosts that project results/events into their own store call this to keep the registry bounded. Non-terminal rows are never touched. Callers must choose a retention window comfortably longer than any waiter lifetime — a pruned process id becomes “unknown process” to late awaits. Re-emitting the same trigger occurrence id after its process has aged out of retention may reserve a fresh delivery process id; occurrence-level idempotency still holds, and ordinary emit replays do not straddle a retention window in practice.

use std::time::{Duration, SystemTime, UNIX_EPOCH};
use lash_core::{PluginError, ProcessRegistry};

async fn prune_week_old(registry: &dyn ProcessRegistry) -> Result<(), PluginError> {
    let now_ms = SystemTime::now()
        .duration_since(UNIX_EPOCH)
        .expect("clock after epoch")
        .as_millis() as u64;
    // Window must exceed any in-flight await's lifetime (ADR 0017).
    let cutoff = now_ms - Duration::from_secs(7 * 24 * 60 * 60).as_millis() as u64;
    let report = registry.prune_terminal_processes(cutoff, None, None).await?;
    eprintln!(
        "pruned {} processes, {} events",
        report.pruned_processes, report.pruned_events
    );
    Ok(())
}

Provided Methods§

Source

fn durability_tier(&self) -> DurabilityTier

Durability tier this process registry provides; defaults to DurabilityTier::Inline.

Source

fn list_live_handle_grants<'life0, 'life1, 'async_trait>( &'life0 self, session_scope: &'life1 SessionScope, ) -> Pin<Box<dyn Future<Output = Result<Vec<(ProcessHandleGrant, ProcessRecord)>, PluginError>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, Self: 'async_trait,

Source

fn has_handle_grant<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, session_scope: &'life1 SessionScope, process_id: &'life2 str, ) -> Pin<Box<dyn Future<Output = Result<bool, PluginError>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, Self: 'async_trait,

Source

fn count_events_through<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, process_id: &'life1 str, event_type: &'life2 str, up_to_sequence: u64, ) -> Pin<Box<dyn Future<Output = Result<u64, PluginError>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, Self: 'async_trait,

Count events of event_type with sequence <= up_to_sequence.

This is the signal-ordinal query: the Nth occurrence of a signal event resolves the Nth durable wait key. The default scans the event log; store backends override it with a COUNT so per-signal cost stays flat instead of growing with a long-lived process’s history.

Source

fn recent_events<'life0, 'life1, 'async_trait>( &'life0 self, process_id: &'life1 str, limit: usize, ) -> Pin<Box<dyn Future<Output = Result<Vec<ProcessEvent>, PluginError>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, Self: 'async_trait,

The most recent limit events, in ascending sequence order.

Observation snapshots use this to show a bounded activity tail without fetching a process’s entire history on every poll. The default scans the event log; store backends override it with ORDER BY … LIMIT.

Dyn Compatibility§

This trait is dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety".

Implementors§