Skip to main content

ForEach

Struct ForEach 

Source
#[non_exhaustive]
pub struct ForEach { pub over: Value, pub item: String, pub max_concurrency: usize, pub collect: Option<String>, pub into: Option<String>, /* private fields */ }
Expand description

Run a task’s function once per element of an array.

{ "id": "infer", "name": "One move per participant",
  "for_each": { "over": { "var": "data.participants" }, "as": "p",
                "max_concurrency": 8,
                "collect": "temp_data.move", "into": "temp_data.moves" },
  "continue_on_error": true,
  "function": { "name": "model_infer", "input": {
    "model": { "var": "temp_data.p.model" },
    "output": "temp_data.move" } } }

The task’s condition is evaluated once. over is then evaluated once, and the function runs once per element with the element at temp_data.<as> and its index at temp_data.<as>_index.

§Every call is isolated

Each call runs against its own copy of the message, taken before the first call, so no call sees another’s writes — not even when they run one at a time. When the calls finish, each is folded back into the message in element order: the errors it recorded, then its writes, then its audit entry. That is what makes max_concurrency a timing knob only: the message comes out the same at every setting.

The fold replays the writes a handler made through TaskContext::set. A write made by reaching into ctx.message_mut() directly is not carried back. The bindings themselves live only in each call’s copy, so neither temp_data.<as> nor temp_data.<as>_index is left behind — unless a handler writes under one of them itself, which is replayed like any other write. collect may not name a path under either.

§Results

collect names the slot each call writes its result to, and into the array the results land in, in element order. An element that failed (a returned Err or a status of 400 or more), or never ran, or wrote nothing at collect, leaves null at its index.

§Failures

The task’s continue_on_error applies per element. A call that fails the task — an Err or a 5xx without continue_on_error — or returns TaskOutcome::Halt stops new calls from starting; calls already running finish. Folding stops at the first element whose record fails the task or halts, so the elements after it contribute nothing — however many had already finished. terminal and halt_on apply once, after the whole fan-out.

Only handler-backed functions may fan out (http_call, enrich, publish_kafka, custom handlers): built-ins run inline, and JSONLogic’s map, filter and reduce already cover per-element transforms.

#[non_exhaustive]: the compiled fields are engine internals. Parse a workflow from JSON to get one.

Fields (Non-exhaustive)§

This struct is marked as non-exhaustive
Non-exhaustive structs could have additional fields added in future. Therefore, non-exhaustive structs cannot be constructed in external crates using the traditional Struct { .. } syntax; cannot be matched against without a wildcard ..; and struct update syntax will not work.
§over: Value

JSONLogic evaluated once, after the task’s condition. It must yield an array; anything else, null included, fails the task. An empty array runs no call.

§item: String

temp_data field holding the element in each call’s view. The JSON key is as. The element’s index is at <as>_index beside it.

§max_concurrency: usize

Calls in flight at once. 1, the default, runs them one at a time.

§collect: Option<String>

Context path each call writes its result to, such as temp_data.move. Requires into. Must not overlap temp_data.<as> or temp_data.<as>_index.

§into: Option<String>

Context path that receives the results as an array in element order. Requires collect.

Implementations§

Source§

impl ForEach

Source

pub fn index_slot(&self) -> String

<as>_index: the sibling slot holding the element’s index.

Trait Implementations§

Source§

impl Clone for ForEach

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for ForEach

Source§

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

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

impl<'de> Deserialize<'de> for ForEach

Source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. 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> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,

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> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
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, !>

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.