SagaCtx

Struct SagaCtx 

Source
pub struct SagaCtx<'a> {
    pub(crate) state: &'a AppState,
    pub(crate) saga_id: u64,
    pub(crate) step_index: AtomicU32,
    pub(crate) forward_step_stack: Mutex<Vec<u32>>,
}
Expand description

Read-only context passed to a saga’s inner async function. Wraps the AppState handle and the saga’s allocated id.

Construct via SagaCtx::new — the durability log requires the per-step counter to start at zero and be owned by the ctx (so concurrent sagas don’t interleave step indices).

Fields§

§state: &'a AppState§saga_id: u64§step_index: AtomicU32

Monotonic step index (0, 1, 2, …) for this saga. Each dispatch / compensate call fetch_add(1)s and writes the resulting index into the saga log. Atomic because saga inner futures may parallelise dispatches in the future (today they don’t, but the cost is one cache line).

§forward_step_stack: Mutex<Vec<u32>>

(codex P1 PR #636 round 4.) Stack of forward-step indices that have completed successfully and are eligible to be undone by the next compensate call. dispatch pushes on success; compensate pops to determine which original forward step it’s reversing, and marks that step compensated in the log. Without this, in-process compensation only writes new compensated rows at fresh indices; the original succeeded rows stay succeeded, so resume-on-restart re-replays them and either no-ops or worse double-applies the inverse.

Mutex<Vec> (rather than a lock-free counter) because saga inner futures could in theory parallelize compensations; in practice they’re serial today, so contention is zero.

Implementations§

Source§

impl<'a> SagaCtx<'a>

Source

pub fn new(state: &'a AppState, saga_id: u64) -> Self

Construct a fresh context for a saga that has just allocated its saga_id (via alloc_saga_id).

Source

pub fn saga_id(&self) -> u64

Saga-id this context belongs to. Used by sagas that need to log progress with the saga prefix.

Source

pub async fn state_lock(&self) -> MutexGuard<'_, State>

Acquire the reducer’s state lock for read-only inspection. Used by sagas that need to inspect post-step state to decide the next step (e.g. RestoreTornOffTab checking whether the source workspace is now empty before issuing the cascade delete). Hold briefly — the reducer is single-mutex.

Source

pub async fn dispatch(&self, cmd: Command) -> Result<Vec<Event>, String>

Dispatch cmd through the srv reducer and apply the emitted events to SQLite + the broadcast bus, exactly like the in-handler reducer-dispatch helpers.

Returns the emitted event vec on success. If the reducer emits any Event::Error, the error message is returned and SQLite/bus side-effects are skipped — the caller must then dispatch compensation for the saga’s already-applied steps.

Source

pub async fn compensate(&self, cmd: Command)

Best-effort compensating dispatch. Same as dispatch but SQLite-write failures are logged and swallowed. Intended for the unwind path: the saga is already returning an error to the caller; throwing on cleanup hides the original cause and prevents subsequent compensating commands from running.

Auto Trait Implementations§

§

impl<'a> !Freeze for SagaCtx<'a>

§

impl<'a> !RefUnwindSafe for SagaCtx<'a>

§

impl<'a> Send for SagaCtx<'a>

§

impl<'a> Sync for SagaCtx<'a>

§

impl<'a> Unpin for SagaCtx<'a>

§

impl<'a> !UnwindSafe for SagaCtx<'a>

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
§

impl<T> Downcast for T
where T: Any,

§

fn into_any(self: Box<T>) -> Box<dyn Any>

Convert Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.
§

fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>

Convert Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be further downcast into Rc<ConcreteType> where ConcreteType implements Trait.
§

fn as_any(&self) -> &(dyn Any + 'static)

Convert &Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &Any’s vtable from &Trait’s.
§

fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

Convert &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &mut Any’s vtable from &mut Trait’s.
§

impl<T> DowncastSync for T
where T: Any + Send + Sync,

§

fn into_any_arc(self: Arc<T>) -> Arc<dyn Any + Sync + Send>

Convert Arc<Trait> (where Trait: Downcast) to Arc<Any>. Arc<Any> can then be further downcast into Arc<ConcreteType> where ConcreteType implements Trait.
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> Instrument for T

§

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

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

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.

§

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

§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns [Action::Follow] only if self and other return Action::Follow. Read more
§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns [Action::Follow] if either self or other returns Action::Follow. Read more
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.
§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

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
§

fn with_current_subscriber(self) -> WithDispatch<Self>

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

impl<A, B, T> HttpServerConnExec<A, B> for T
where B: Body,