Skip to main content

TaskContext

Struct TaskContext 

Source
pub struct TaskContext<'a> { /* private fields */ }
Expand description

Per-call execution context handed to AsyncFunctionHandler::execute.

Borrows the message and datalogic engine for the duration of the handler call; collects Change entries that the workflow executor folds into the audit trail when the handler returns. Drop semantics are trivial — there is nothing to flush; the executor extracts the buffered changes via into_changes().

Implementations§

Source§

impl<'a> TaskContext<'a>

Source

pub fn new( message: &'a mut Message, datalogic: &'a Arc<DatalogicEngine>, ) -> Self

Construct a new context. Mostly engine-internal — handlers receive a pre-built &mut TaskContext from the executor — but exposed pub so tests and benchmarks can drive AsyncFunctionHandler::execute directly without going through Engine::process_message. A context built this way reports None from Self::workflow_id, Self::task_id and Self::loop_counter — there is no workflow run to describe, and inventing ids would be worse than admitting their absence.

Source

pub fn workflow_id(&self) -> Option<&str>

Id of the workflow being executed, when the engine built this context.

None for a context built with Self::new — a test or benchmark driving a handler directly is not inside a workflow run.

let ctx = TaskContext::new(&mut message, &datalogic);
assert_eq!(ctx.workflow_id(), None);
Source

pub fn task_id(&self) -> Option<&str>

Id of the task being executed, when the engine built this context.

Always a leaf task’s id. Handlers run only on leaf tasks — a task group is span bookkeeping recorded on the task that opens it, never a dispatch target — so a group id can never appear here.

None for a context built with Self::new.

Source

pub fn loop_counter(&self) -> Option<i64>

Sweep index of the enclosing looping workflow, or None when the workflow does not carry a loop.

This is a different fact from identity being unknown: a handler in a non-looping workflow has both ids and no counter.

Worth preferring over reading the counter out of temp_data, which only works when the host gave LoopConfig a counter name and the handler hardcodes that path. A loop with no named counter writes to no path at all, and its sweep index is reachable no other way.

Source

pub fn secret(&self, name: &str) -> Option<&OwnedDataValue>

A secret by dotted name, from the store the host configured through crate::EngineBuilder::with_secrets.

For handlers whose config names a key ("key_name": "partner_hmac") rather than embedding a crate::Template — a Template field can simply read {"secret": "partner_hmac"} and needs nothing here.

None when the key is not declared, and always None for a context built with Self::new. The contract for what you do with the value is one line: a handler must not write a secret-derived value into the message. Nothing in the engine records what this returns; whether it stays unrecorded is the handler’s business from here on.

Source

pub fn message(&self) -> &Message

Borrow the message under processing. Use this when you need to inspect the message id, payload, or audit trail; for reading and mutating the data / metadata / temp_data context, prefer the typed helpers on TaskContext itself.

Source

pub fn message_mut(&mut self) -> &mut Message

Mutable access to the message. Prefer the typed helpers (set, add_error) over poking at message.context directly — direct mutations bypass the audit trail.

Source

pub fn datalogic(&self) -> &Arc<DatalogicEngine>

Shared datalogic engine, in case the handler needs to evaluate ad-hoc JSONLogic. Most handlers can ignore this argument.

Source

pub fn data(&self) -> &OwnedDataValue

Read-only view of data. Returns &OwnedDataValue::Null if missing (mirrors the Index fallback semantics of serde_json::Value).

Source

pub fn metadata(&self) -> &OwnedDataValue

Read-only view of metadata.

Source

pub fn temp_data(&self) -> &OwnedDataValue

Read-only view of temp_data.

Source

pub fn context(&self) -> &OwnedDataValue

The full {data, metadata, temp_data} tree — the root every workflow JSONLogic expression is written against.

Self::data / Self::metadata / Self::temp_data expose the three slots individually; this is the whole-context accessor, so handlers do not have to reach through ctx.message().context.

Note payload is not part of this tree, and therefore not part of the JSONLogic evaluation context — {"var": "payload.foo"} resolves to nothing. Parse the payload into data first.

Source

pub fn eval(&self, logic: &Logic) -> Result<OwnedDataValue>

Evaluate a pre-compiled expression against the message context, on the worker thread’s pooled arena.

The same path crate::engine::executor::evaluate_condition takes, but returning the value instead of collapsing it to a bool, and surfacing evaluation failures as Err instead of false. That difference is deliberate: a condition that fails to evaluate should not run its task, whereas a handler reading a config value needs to know the read failed.

§Errors

DataflowError::LogicEvaluation if the expression fails to evaluate.

Source

pub fn eval_json(&self, logic: &Logic) -> Result<JsonValue>

As Self::eval, projected straight from the arena to serde_json::Value in one walk — no OwnedDataValue intermediate and no serde_json::from_value rebuild.

Source

pub fn eval_to_plain_string(&self, logic: &Logic) -> Result<String>

As Self::eval, coerced to a plain string: a JSON string result yields its contents, anything else its compact JSON form.

§This disagrees with datalogic-rs on purpose

datalogic-rs’s String: FromDataValue — and therefore Session::eval_str — keeps the JSON quoting, so a string result comes back from it as "\"abc\"". This method returns abc.

The name says plain_string rather than to_string precisely so the difference is visible at the call site: two string semantics in one ecosystem is a footgun, and these values end up in URL paths and message keys. A test pins both sides, so it fails if either changes.

Source

pub fn get(&self, path: &str) -> Option<&OwnedDataValue>

Look up a value by dot-path against the full context tree (rooted at the unified {data, metadata, temp_data} object). Returns None if the path doesn’t resolve.

Use the same path syntax as JSONLogic: "data.user.name", "temp_data.items.0", "metadata.progress.status_code".

Source

pub fn set(&mut self, path: &str, value: OwnedDataValue)

Set a value at a dot-path on the context. Records a Change on the audit trail when message.capture_changes is true; otherwise the write happens but no audit entry is buffered.

Intermediate objects/arrays are created on demand; see crate::engine::utils::set_nested_value for the exact semantics (numeric segments → arrays, # prefix → escaped object key, etc.).

Source

pub fn set_json(&mut self, path: &str, value: &JsonValue)

Same as Self::set but accepts a serde_json::Value (bridges through OwnedDataValue::from). Convenience for handlers that already speak serde_json::Value.

Source

pub fn add_error(&mut self, error: ErrorInfo)

Append an error to message.errors. Convenience for ctx.message_mut().add_error(...).

Source

pub fn into_changes(self) -> Vec<Change>

Drain the accumulated changes. The workflow executor calls this after the handler returns to fold them into the audit trail; tests and benchmarks driving the trait directly can use it to inspect what the handler buffered.

Auto Trait Implementations§

§

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

§

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

§

impl<'a> Freeze for TaskContext<'a>

§

impl<'a> Send for TaskContext<'a>

§

impl<'a> Sync for TaskContext<'a>

§

impl<'a> Unpin for TaskContext<'a>

§

impl<'a> UnsafeUnpin for TaskContext<'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
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

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, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

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.