Skip to main content

Skill

Trait Skill 

Source
pub trait Skill:
    Send
    + Sync
    + Debug
    + 'static {
    // Required methods
    fn descriptor(&self) -> SkillDescriptor;
    fn invoke<'life0, 'life1, 'life2, 'async_trait>(
        &'life0 self,
        cx: &'life1 mut StepCtx<'life2>,
        input: Tainted<Value>,
    ) -> Pin<Box<dyn Future<Output = Result<Outcome, SkillError>> + Send + 'async_trait>>
       where Self: 'async_trait,
             'life0: 'async_trait,
             'life1: 'async_trait,
             'life2: 'async_trait;

    // Provided methods
    fn compensation(&self) -> Compensation { ... }
    fn compensate<'life0, 'life1, 'life2, 'life3, 'async_trait>(
        &'life0 self,
        _cx: &'life1 mut StepCtx<'life2>,
        _output: &'life3 Tainted<Value>,
    ) -> Pin<Box<dyn Future<Output = Result<(), SkillError>> + Send + 'async_trait>>
       where Self: 'async_trait,
             'life0: 'async_trait,
             'life1: 'async_trait,
             'life2: 'async_trait,
             'life3: 'async_trait { ... }
}
Expand description

A stateless unit of logic.

Statelessness is not a style preference: it is what makes replay sound. All state lives in the journal, so re-running a skill against a replayed context reproduces its decisions exactly.

Note the absent variant: there is no Outcome::SuspensionRequired. Suspension is cx.suspend().await, so skill authors never hand-roll state serialization — the runtime persists the frame and drops the task.

Required Methods§

Source

fn descriptor(&self) -> SkillDescriptor

Source

fn invoke<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, cx: &'life1 mut StepCtx<'life2>, input: Tainted<Value>, ) -> Pin<Box<dyn Future<Output = Result<Outcome, SkillError>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait,

Provided Methods§

Source

fn compensation(&self) -> Compensation

This step’s place in the saga.

Defaults to Compensation::Undeclared, which is resolved against the journal rather than waved through — see that variant.

Source

fn compensate<'life0, 'life1, 'life2, 'life3, 'async_trait>( &'life0 self, _cx: &'life1 mut StepCtx<'life2>, _output: &'life3 Tainted<Value>, ) -> Pin<Box<dyn Future<Output = Result<(), SkillError>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, 'life3: 'async_trait,

Undo this step, because a later one failed.

Called in reverse order of completion, with the output this step produced. The context is a full StepCtx: compensating effects are journaled, retried, reconciled, and replayed exactly like forward ones, because they are exposed to the same world and can fail the same ways.

Errors are not retried by unwinding further. A failed compensation is not a problem more compensation solves, so the run is quarantined and an operator is told which step could not be undone.

Dyn Compatibility§

This trait is dyn compatible.

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

Implementors§