pub struct Runtime<S> { /* private fields */ }Expand description
Executes effects against a store. Cheap to clone; clones share state.
Implementations§
Source§impl<S: EffectStore> Runtime<S>
impl<S: EffectStore> Runtime<S>
Sourcepub fn compensation(
&self,
name: impl Into<String>,
key: impl Display,
) -> CompensationBuilder<'_, S>
pub fn compensation( &self, name: impl Into<String>, key: impl Display, ) -> CompensationBuilder<'_, S>
Starts undoing the closure effect (name, key). See
CompensationBuilder::run.
Source§impl<S: EffectStore> Runtime<S>
impl<S: EffectStore> Runtime<S>
Sourcepub async fn recover(&self) -> Result<RecoveryReport, RuntimeError>
pub async fn recover(&self) -> Result<RecoveryReport, RuntimeError>
One recovery pass, in two steps.
- Every effect whose worker’s lease expired mid-attempt or
mid-verification becomes
Unknown, neverFailed: it may have changed the outside world. - Every unsettled effect nobody holds (see
Self::pending) whose name has a registered handler is finished from its stored input, exactly as if its caller had called again: verified, re-run if that is safe, or escalated. This includes effects leftPendingby a crash. Effects waiting for an operator, and retries scheduled for later, are left alone. Unsettled closure effects are reported asunhandled: only a caller can re-run them.
Effects are resumed one at a time, so a pass lasts as long as their retries and verifications take. Safe to run from several workers at once: every change happens under a lease.
§Errors
RuntimeError::Store if the store fails. Progress made before the
failure is kept. A handler that cannot run is reported in
resume_errors instead.
Sourcepub async fn run_recovery(&self, interval: Duration)
pub async fn run_recovery(&self, interval: Duration)
Runs Self::recover every interval, forever, followed by
Self::prune when the runtime has a
retention policy. Spawn it:
tokio::spawn({
let runtime = runtime.clone();
async move { runtime.run_recovery(Duration::from_secs(30)).await }
});A failed pass is logged and retried at the next tick.
Sourcepub async fn pending(
&self,
after: Option<EffectId>,
limit: usize,
) -> Result<Vec<EffectRecord>, RuntimeError>
pub async fn pending( &self, after: Option<EffectId>, limit: usize, ) -> Result<Vec<EffectRecord>, RuntimeError>
Effects waiting for a caller to re-run them or an operator to decide,
ordered by creation, limit at a time after after.
These are the effects that are unsettled with nobody working on
them: Pending (for example a worker died during a backoff wait),
Executing or Verifying with an expired lease (not yet recovered),
Unknown, NeedsIntervention, AwaitingApproval, an interrupted
Compensating, and CompensationFailed.
§Errors
RuntimeError::Store if the store fails.
Sourcepub async fn resolve(
&self,
id: EffectId,
resolution: Resolution,
actor: impl Into<String>,
note: impl Into<String>,
) -> Result<EffectRecord, RuntimeError>
pub async fn resolve( &self, id: EffectId, resolution: Resolution, actor: impl Into<String>, note: impl Into<String>, ) -> Result<EffectRecord, RuntimeError>
Records an operator’s decision about an effect that is Unknown or
NeedsIntervention. actor identifies the operator (e.g.
operator:alice); note says why, for the audit trail.
§Errors
RuntimeError::Store wrapping:
StoreError::NotFoundfor an unknown id;StoreError::InvalidTransitionif the effect is not unresolved, for example already committed;StoreError::LeaseHeldwhile a caller or worker is working on it;StoreError::VersionConflictif it changed during the call.
Sourcepub async fn approve(
&self,
id: EffectId,
actor: impl Into<String>,
note: impl Into<String>,
) -> Result<EffectRecord, RuntimeError>
pub async fn approve( &self, id: EffectId, actor: impl Into<String>, note: impl Into<String>, ) -> Result<EffectRecord, RuntimeError>
Approves an effect waiting in AwaitingApproval. It becomes
Pending: a caller’s next call runs it, and so does recovery for a
registered handler. actor is recorded as the approver.
§Errors
As for Self::resolve; InvalidTransition if it is not awaiting
approval.
Sourcepub async fn deny(
&self,
id: EffectId,
actor: impl Into<String>,
reason: impl Into<String>,
) -> Result<EffectRecord, RuntimeError>
pub async fn deny( &self, id: EffectId, actor: impl Into<String>, reason: impl Into<String>, ) -> Result<EffectRecord, RuntimeError>
Denies an effect waiting in AwaitingApproval. It ends Rejected,
with reason as its error.
§Errors
As for Self::approve.
Source§impl<S: EffectStore> Runtime<S>
impl<S: EffectStore> Runtime<S>
Sourcepub async fn prune(&self) -> Result<PruneReport, RuntimeError>
pub async fn prune(&self) -> Result<PruneReport, RuntimeError>
Deletes the settled records the retention policy
says are old enough, in batches, with their audit trails. Does
nothing without a policy. Self::run_recovery calls it every
round; call it yourself to prune on another schedule.
§Errors
RuntimeError::Store if the store fails. Batches deleted before
the failure stay deleted.
Source§impl<S: EffectStore> Runtime<S>
impl<S: EffectStore> Runtime<S>
Sourcepub fn builder(store: S) -> RuntimeBuilder<S>
pub fn builder(store: S) -> RuntimeBuilder<S>
Starts configuring a runtime.
Sourcepub fn effect(
&self,
name: impl Into<String>,
key: impl Display,
) -> EffectBuilder<S>
pub fn effect( &self, name: impl Into<String>, key: impl Display, ) -> EffectBuilder<S>
Describes an effect: name is its type (e.g. payment.charge),
key identifies this occurrence (e.g. the order id). Every call with
the same name and key refers to the same effect.
Sourcepub fn submit<H: EffectHandler>(
&self,
key: impl Display,
input: H::Input,
) -> Submission<'_, S, H>
pub fn submit<H: EffectHandler>( &self, key: impl Display, input: H::Input, ) -> Submission<'_, S, H>
Runs a registered handler’s effect with input, or attaches to an
earlier run with the same key. Await the returned Submission.
Behaves like EffectBuilder::run, with the handler’s properties.
The input is stored in full, so recovery can finish the effect if
this process dies.
Sourcepub fn compensate<H: EffectHandler>(
&self,
key: impl Display,
) -> CompensationSubmission<'_, S, H>
pub fn compensate<H: EffectHandler>( &self, key: impl Display, ) -> CompensationSubmission<'_, S, H>
Undoes a registered, compensable handler’s
effect. Await the returned submission. See
compensation.
Sourcepub async fn wait<T: DeserializeOwned>(
&self,
id: EffectId,
timeout: Duration,
) -> Result<EffectOutcome<T>, RuntimeError>
pub async fn wait<T: DeserializeOwned>( &self, id: EffectId, timeout: Duration, ) -> Result<EffectOutcome<T>, RuntimeError>
Waits until nobody is working on effect id, or timeout passes, and
reports where it stands. For a caller that got
EffectOutcome::InProgress.
Returns InProgress if the effect is still being worked on at the
deadline, or if it is unsettled and nobody holds it (for example a
worker crashed while waiting to retry). Running the effect again then
takes it over.
§Errors
RuntimeError::Store if the store fails or has no such effect, and
RuntimeError::Output if a committed output does not deserialize
into T.