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 Self: 'async_trait,
'life0: '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 Self: 'async_trait,
'life0: 'async_trait,
'life1: '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 Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: '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 Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: '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 Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait;
fn list_handle_grants<'life0, 'life1, 'async_trait>(
&'life0 self,
session_scope: &'life1 SessionScope,
) -> Pin<Box<dyn Future<Output = Result<Vec<ProcessHandleGrantEntry>, PluginError>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: '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 Self: 'async_trait,
'life0: 'async_trait,
'life1: '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 Self: 'async_trait,
'life0: 'async_trait,
'life1: '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 Self: 'async_trait,
'life0: 'async_trait,
'life1: '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 Self: 'async_trait,
'life0: 'async_trait,
'life1: '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 Self: 'async_trait,
'life0: 'async_trait,
'life1: '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 Self: 'async_trait,
'life0: 'async_trait,
'life1: '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 Self: 'async_trait,
'life0: 'async_trait,
'life1: '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 Self: 'async_trait,
'life0: 'async_trait,
'life1: '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 Self: 'async_trait,
'life0: 'async_trait,
'life1: '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 Self: 'async_trait,
'life0: 'async_trait,
'life1: '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 Self: 'async_trait,
'life0: 'async_trait,
'life1: '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 Self: 'async_trait,
'life0: 'async_trait,
'life1: '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 Self: 'async_trait,
'life0: 'async_trait,
'life1: '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 Self: 'async_trait,
'life0: '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 Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait;
fn list_non_terminal<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Result<Vec<ProcessRecord>, PluginError>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait;
fn live_reference_summary<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Result<Vec<ProcessLiveReferenceSummary>, PluginError>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: '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 Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: '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 Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: '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 Self: 'async_trait,
'life0: 'async_trait,
'life1: '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 Self: 'async_trait,
'life0: 'async_trait,
'life1: '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 Self: 'async_trait,
'life0: 'async_trait,
'life1: '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 Self: 'async_trait,
'life0: '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<ProcessHandleGrantEntry>, PluginError>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: '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 Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: '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 Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: '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 Self: 'async_trait,
'life0: 'async_trait,
'life1: '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§
fn register_process<'life0, 'async_trait>(
&'life0 self,
registration: ProcessRegistration,
) -> Pin<Box<dyn Future<Output = Result<ProcessRecord, PluginError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Sourcefn 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
Self: 'async_trait,
'life0: 'async_trait,
'life1: '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
Self: 'async_trait,
'life0: 'async_trait,
'life1: '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.
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
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: '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
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: '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
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
fn list_handle_grants<'life0, 'life1, 'async_trait>(
&'life0 self,
session_scope: &'life1 SessionScope,
) -> Pin<Box<dyn Future<Output = Result<Vec<ProcessHandleGrantEntry>, PluginError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: '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
Self: 'async_trait,
'life0: 'async_trait,
'life1: '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
Self: 'async_trait,
'life0: 'async_trait,
'life1: '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
Self: 'async_trait,
'life0: 'async_trait,
'life1: '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
Self: 'async_trait,
'life0: 'async_trait,
'life1: '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
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Sourcefn 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
Self: 'async_trait,
'life0: 'async_trait,
'life1: '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
Self: 'async_trait,
'life0: 'async_trait,
'life1: '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.
Sourcefn 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
Self: 'async_trait,
'life0: 'async_trait,
'life1: '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
Self: 'async_trait,
'life0: 'async_trait,
'life1: '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.
Sourcefn 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
Self: 'async_trait,
'life0: 'async_trait,
'life1: '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
Self: 'async_trait,
'life0: 'async_trait,
'life1: '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.
Sourcefn 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
Self: 'async_trait,
'life0: 'async_trait,
'life1: '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
Self: 'async_trait,
'life0: 'async_trait,
'life1: '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.
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
Self: 'async_trait,
'life0: 'async_trait,
'life1: '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
Self: 'async_trait,
'life0: 'async_trait,
'life1: '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
Self: 'async_trait,
'life0: 'async_trait,
'life1: '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
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Sourcefn 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
Self: 'async_trait,
'life0: '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
Self: 'async_trait,
'life0: '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.
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
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Sourcefn list_non_terminal<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Result<Vec<ProcessRecord>, PluginError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn list_non_terminal<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Result<Vec<ProcessRecord>, PluginError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: '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.
Sourcefn live_reference_summary<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Result<Vec<ProcessLiveReferenceSummary>, PluginError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn live_reference_summary<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Result<Vec<ProcessLiveReferenceSummary>, PluginError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Count non-terminal process rows by their captured definition and execution-environment references.
Sourcefn 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
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: '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
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: '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.
Sourcefn 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
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: '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
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: '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.
Sourcefn 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
Self: 'async_trait,
'life0: 'async_trait,
'life1: '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
Self: 'async_trait,
'life0: 'async_trait,
'life1: '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.
Sourcefn 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
Self: 'async_trait,
'life0: 'async_trait,
'life1: '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
Self: 'async_trait,
'life0: 'async_trait,
'life1: '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.
Sourcefn complete_process_lease<'life0, 'life1, 'async_trait>(
&'life0 self,
completion: &'life1 ProcessLeaseCompletion,
) -> Pin<Box<dyn Future<Output = Result<(), PluginError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: '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
Self: 'async_trait,
'life0: 'async_trait,
'life1: '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.
Sourcefn 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
Self: 'async_trait,
'life0: '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
Self: 'async_trait,
'life0: '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§
Sourcefn durability_tier(&self) -> DurabilityTier
fn durability_tier(&self) -> DurabilityTier
Durability tier this process registry provides; defaults to
DurabilityTier::Inline.
fn list_live_handle_grants<'life0, 'life1, 'async_trait>(
&'life0 self,
session_scope: &'life1 SessionScope,
) -> Pin<Box<dyn Future<Output = Result<Vec<ProcessHandleGrantEntry>, PluginError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: '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
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Sourcefn 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
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: '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
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: '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.
Sourcefn 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
Self: 'async_trait,
'life0: 'async_trait,
'life1: '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
Self: 'async_trait,
'life0: 'async_trait,
'life1: '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".