Skip to main content

FlowHandle

Struct FlowHandle 

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

A single running flow. Owns the step cursor (seq), so it is used by one task via &mut; the manager stays &self-concurrent for many flows.

Dropping a handle without complete leaves the flow running with its lease — exactly the crash shape recovery resumes.

Implementations§

Source§

impl FlowHandle

Source

pub fn flow_id(&self) -> &FlowId

This flow’s storage id.

Source

pub fn entry_status(&self) -> FlowStatus

The flow’s status when this handle was opened. completed means this is a pure-replay handle (a rerun of an already-finished flow); running or failed means a live entry/resume. The front end reads this to tell the user “resumed” vs. “already completed”.

Source

pub fn is_replay_only(&self) -> bool

Whether this handle is a completed-flow pure replay — every step is substituted from the journal and no effect will fire.

Source

pub async fn execute_step<F>(&mut self, request: &Request, effect: F) -> Outcome

Execute one journaled step: an intercepted effect wrapped in the Tier 1 engine (retries/timeout/breaker are attempts of this one step). On replay the recorded outcome is substituted and effect is never called.

Source

pub async fn execute_step_with_idempotency_key<F>( &mut self, request: &Request, idempotency_key: Option<&str>, effect: F, ) -> Outcome

execute_step, carrying the idempotency key the adapter minted and injected for this call (contracts/adapter-pack.md “Idempotency-key injection”, rule 3). The key is journaled in the step’s running record, so a resume that re-executes a crashed step can read it back (recorded_idempotency_key) and inject the SAME key — making the at-least-once re-execution deduplicable on the provider side. The key never feeds the step key (args_hash is unchanged by injection), so replay matching is unaffected.

Source

pub fn recorded_idempotency_key(&self, step_key: &str) -> Option<String>

The idempotency key recorded for the flow’s NEXT step, when that record is a crashed (running) step under the same step_key — the resume-reuse read of contracts/adapter-pack.md “Idempotency-key injection” rule 3. Adapters call this before executing an injectable step: Some(key) means a previous run crashed mid-step after minting key, and re-executing with the SAME key lets the provider deduplicate the at-least-once re-execution. None — mint fresh — on a fresh step, a terminal record (the step will be substituted, no key is sent), a diverging key, an abandoned replay, a pure-replay handle, or a journal read failure (resilience first).

Source

pub fn journal_time(&mut self, key: &str, now_ms: i64) -> Result<i64, KeelError>

Journal (or replay) a virtualized clock read under the front-end-supplied key (the module-docs convention, e.g. py:time.time#-). On replay the recorded value is substituted so a resumed flow sees the same time; live, now_ms is recorded and returned (spec §4.4).

§Errors

KEEL-E031 if this step diverges from the journal under fail.

Source

pub fn journal_random( &mut self, key: &str, bytes: Vec<u8>, ) -> Result<Vec<u8>, KeelError>

Journal (or replay) a virtualized random draw under the front-end-supplied key (e.g. py:random.random#-). On replay the recorded bytes are substituted; live, bytes are recorded and returned.

§Errors

KEEL-E031 if this step diverges from the journal under fail.

Source

pub fn complete(&mut self, status: FlowStatus) -> Result<(), KeelError>

Move the flow to a terminal status on scope exit. Idempotent-ish: a second call re-stamps the status — except a completed flow is immutable at the journal (complete_flow refuses to demote it), so re-running a finished flow can never flip it to failed/dead.

Unlike Self::record, a failed write here is NOT degraded to a warn! — it is returned as a KEEL-E040 KeelError (issue #14: a same-process foreign SQLite connection opened and closed against a live journal.db can trigger a WAL-checkpoint-on-close race that silently drops a still-open core’s pending native writes; see docs/superpowers/ledgers/agent-first-class/ws5-task-3-report.md for the discovery narrative). Losing the terminal-status write is a correctness bug (the journal can permanently disagree with the caller about how the flow ended), so it must reach the caller loudly instead of vanishing into a log line. self.completed is set regardless of success or failure: a completed attempt is “done” from the handle’s perspective either way, and Drop should not also complain about it.

Source

pub fn complete_success(&mut self) -> Result<(), KeelError>

Mark the flow completed (the success scope exit).

Source

pub fn complete_failed(&mut self) -> Result<(), KeelError>

Mark the flow failed (a non-retryable failure exit).

Trait Implementations§

Source§

impl Debug for FlowHandle

Source§

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

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

impl Drop for FlowHandle

Source§

fn drop(&mut self)

Executes the destructor for this type. Read more
Source§

fn pin_drop(self: Pin<&mut Self>)

🔬This is a nightly-only experimental API. (pin_ergonomics)
Execute the destructor for this type, but different to Drop::drop, it requires self to be pinned. Read more

Auto Trait Implementations§

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: 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