#[non_exhaustive]pub struct Task {
pub id: String,
pub name: String,
pub description: Option<String>,
pub condition: Value,
pub function: FunctionConfig,
pub continue_on_error: bool,
pub terminal: bool,
pub halt_on: HaltOn,
/* private fields */
}Expand description
A single processing unit within a workflow (also known as an Action in rules-engine terminology).
Tasks execute functions with optional conditions and error handling. They are processed sequentially within a workflow, allowing later tasks to depend on results from earlier ones.
§Example JSON Definition
{
"id": "validate_user",
"name": "Validate User Data",
"description": "Ensures user data meets requirements",
"condition": {">=": [{"var": "data.order.total"}, 1000]},
"function": {
"name": "validation",
"input": { "rules": [...] }
},
"continue_on_error": false,
"terminal": false,
"halt_on": "failure"
}A single unit of work inside a workflow.
#[non_exhaustive]: construct through Task::action and assign the
public fields you need, or parse a workflow from JSON. Field reads and
writes are unaffected, and .. patterns keep working.
The attribute exists because three of this struct’s fields — id_arc,
compiled_condition, group_starts — are engine internals documented as
not part of the stable API, yet struct-literal construction forced every
caller to name them. Field additions had already broken those callers twice
(3.3.0, 3.6.0); this is the change that stops it.
Fields (Non-exhaustive)§
This struct is marked as non-exhaustive
Struct { .. } syntax; cannot be matched against without a wildcard ..; and struct update syntax will not work.id: StringUnique identifier for the task within the workflow.
name: StringHuman-readable name for the task.
description: Option<String>Optional description explaining what the task does.
condition: ValueJSONLogic condition that determines if the task should execute.
Conditions can access any context field (data, metadata, temp_data).
Defaults to true (always execute).
function: FunctionConfigThe function configuration specifying what operation to perform. Can be a built-in function (map, validation) or a custom function.
continue_on_error: boolWhether to continue workflow execution if this task fails.
When true, errors are recorded but don’t stop the workflow.
Defaults to false.
“Fails” means a 5xx outcome or a returned Err — not every
unsuccessful task. A 4xx is logged as a warning and the workflow
carries on regardless of this flag, so continue_on_error: false after a
validation task does not stop the tasks that follow it: a failing rule
returns 400. To gate on an outcome, use Task::halt_on; to reject the
whole message, return an Err from a handler.
terminal: boolWhether running this task ends the workflow. Defaults to false.
terminal is a statement about position — “nothing after this runs” —
not about outcome:
- a false
conditionmeans the task never ran, so nothing halts; TaskOutcome::Skipdoes not halt, for the same reason;- a task that failed under
continue_on_error: truestill halts, and its error is still recorded onmessage.errors().
Halting stops this workflow only; later workflows registered on the same
engine still process the message. Inside a workflow carrying a
LoopConfig it breaks the whole
loop, not one sweep — the same scope as
TaskOutcome::Halt.
The audit-trail entry keeps the task’s own status (200, 404, …)
rather than HALT_STATUS_CODE: the task did its job, and a map that
wrote a 404 response body should not report “a filter halted here”.
For the outcome axis — “halt only if this task failed” — see
Task::halt_on.
halt_on: HaltOnHalt the workflow based on this task’s outcome. Defaults to
HaltOn::Never.
The complement of Task::terminal: terminal is about position and
halts whatever happened, halt_on is about what happened and halts only
then. The two combine as terminal || (halt_on matched) — terminal is
strictly stronger, so setting both is redundant rather than contradictory.
This is what lets an assertion reject. A validation task returns 400
when a rule fails, which is not covered by
continue_on_error, so without halt_on the
tasks after it still run:
{ "id": "check_state", "halt_on": "failure",
"function": { "name": "validation", "input": { "rules": [ … ] } } }Failure means a recorded status of 400 or above — the same
threshold the executor already splits on to warn (4xx) and to record
TASK_STATUS_ERROR (5xx) — or a handler returning Err, recorded as
500. It is deliberately not “the task appended to
message.errors()”: a handler may call
TaskContext::add_error and still
return Success, and that does not halt.
| The task … | terminal: true | halt_on: "failure" |
|---|---|---|
never ran (its condition, or its group’s, was false) | no | no |
returned TaskOutcome::Skip | no | no |
returned Success, or a 2xx–3xx status | halts | no |
returned TaskOutcome::Halt | halts already | halts already |
| returned a 4xx status | halts | halts |
returned 5xx, continue_on_error: true | halts | halts |
returned 5xx, continue_on_error: false | error propagates | error propagates |
handler returned Err, continue_on_error: true | halts | halts |
handler returned Err, continue_on_error: false | error propagates | error propagates |
called add_error but returned Success | halts | no |
The two “error propagates” rows are not an omission: the executor returns
Err before either flag is consulted, which abandons the rest of this
workflow — everything halting would have done — and additionally reaches
the caller. They differ in exactly one shape: a workflow carrying a
loop whose own
continue_on_error is true, where the error advances to the next sweep
while a halt would break the loop. Set continue_on_error: false on the
workflow if the loop must stop.
Everything terminal documents about scope applies unchanged: halting
stops this workflow only, later workflows still process the message, it
breaks a whole loop rather than one sweep, and the audit entry keeps the
task’s own status — 400, not HALT_STATUS_CODE. Halting is therefore
not a security control: to stop a message outright return an Err, or
gate the following workflow on
EngineBuilder::with_error_context_path.
Implementations§
Source§impl Task
impl Task
Sourcepub fn action(id: &str, name: &str, function: FunctionConfig) -> Self
pub fn action(id: &str, name: &str, function: FunctionConfig) -> Self
Create a task (action) with default settings.
This is a convenience constructor for the IFTTT-style rules engine pattern,
creating an action that always executes (condition defaults to true).
§Arguments
id- Unique identifier for the actionname- Human-readable namefunction- The function configuration to execute