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
impl FlowHandle
Sourcepub fn entry_status(&self) -> FlowStatus
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”.
Sourcepub fn is_replay_only(&self) -> bool
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.
Sourcepub async fn execute_step<F>(&mut self, request: &Request, effect: F) -> Outcome
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.
Sourcepub async fn execute_step_with_idempotency_key<F>(
&mut self,
request: &Request,
idempotency_key: Option<&str>,
effect: F,
) -> Outcome
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.
Sourcepub fn recorded_idempotency_key(&self, step_key: &str) -> Option<String>
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).
Sourcepub fn journal_time(&mut self, key: &str, now_ms: i64) -> Result<i64, KeelError>
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.
Sourcepub fn journal_random(
&mut self,
key: &str,
bytes: Vec<u8>,
) -> Result<Vec<u8>, KeelError>
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.
Sourcepub fn complete(&mut self, status: FlowStatus) -> Result<(), KeelError>
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.
Sourcepub fn complete_success(&mut self) -> Result<(), KeelError>
pub fn complete_success(&mut self) -> Result<(), KeelError>
Mark the flow completed (the success scope exit).
Sourcepub fn complete_failed(&mut self) -> Result<(), KeelError>
pub fn complete_failed(&mut self) -> Result<(), KeelError>
Mark the flow failed (a non-retryable failure exit).