Skip to main content

Saga

Struct Saga 

Source
pub struct Saga { /* private fields */ }
Expand description

Saga: a sequence of steps with structured compensations.

Each step has a forward action and a compensation. If any step fails, all previously-completed compensations run in reverse order. This is the distributed equivalent of structured finalizers.

§Design Principles

  • Compensations are deterministic: Given the same inputs, compensations produce the same effects. This enables lab testing of failure scenarios.
  • Reverse order: Compensations run last-to-first, ensuring that later steps’ effects are undone before earlier steps’.
  • Budget-aware: In Phase 1+, compensations will be budget-constrained (they are finalizers, which run under masked cancellation).
  • Trace-aware: Each step and compensation emits trace events.

§API Pattern

The compensation closure captures its own context. The forward action returns a value for the caller to use in subsequent steps.

use asupersync::remote::Saga;

let mut saga = Saga::new();

// Step 1: Create resource — compensation captures what it needs
let id = "resource-1".to_string();
let id_for_comp = id.clone();
saga.step(
    "create resource",
    || Ok(id),
    move || format!("deleted {id_for_comp}"),
)?;

// Step 2: Configure — no value needed for compensation
saga.step("configure", || Ok(()), || "reset config".into())?;

// Complete on success
saga.complete();

Implementations§

Source§

impl Saga

Source

pub fn new() -> Self

Creates a new empty saga.

Source

pub fn state(&self) -> SagaState

Returns the current saga state.

Source

pub fn completed_steps(&self) -> StepIndex

Returns the number of completed steps.

Source

pub fn compensation_results(&self) -> &[CompensationResult]

Returns the compensation results (populated after abort).

Source

pub fn step<T>( &mut self, description: &str, action: impl FnOnce() -> Result<T, String>, compensate: impl FnOnce() -> String + Send + 'static, ) -> Result<T, SagaStepError>

Executes a forward step and registers its compensation.

The forward action runs immediately. If it succeeds, the compensation closure is registered for potential rollback. If it fails, the saga enters the compensating state and runs all registered compensations in reverse order.

The compensation closure should capture whatever context it needs to undo the forward action’s effect (e.g., clone the resource ID before passing it to the step).

§Errors

Returns SagaStepError if the forward action fails. In that case, compensations have already been executed before this returns.

Source

pub fn complete(&mut self)

Marks the saga as successfully completed.

After completion, the registered compensations are dropped (they are no longer needed since all steps succeeded).

§Panics

Panics if the saga is not in Running state.

Source

pub fn abort(&mut self)

Explicitly aborts the saga, running compensations in reverse order.

This is called when the caller wants to roll back, even if no step has failed. For example, when cancellation is requested.

§Panics

Panics if the saga is not in Running state.

Trait Implementations§

Source§

impl Debug for Saga

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for Saga

Source§

fn default() -> Self

Returns the “default value” for a type. Read more
Source§

impl Drop for Saga

Source§

fn drop(&mut self)

Executes the destructor for this type. Read more

Auto Trait Implementations§

§

impl Freeze for Saga

§

impl !RefUnwindSafe for Saga

§

impl Send for Saga

§

impl !Sync for Saga

§

impl Unpin for Saga

§

impl UnsafeUnpin for Saga

§

impl !UnwindSafe for Saga

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, _span: NoopSpan) -> Self

Instruments this future with a span (no-op when disabled).
Source§

fn in_current_span(self) -> Self

Instruments this future with the current span (no-op when disabled).
Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more