Skip to main content

dataflow_rs/engine/
task.rs

1//! # Task Module
2//!
3//! This module defines the `Task` structure, which represents a single
4//! processing unit within a workflow. Tasks are the fundamental building
5//! blocks of data processing pipelines.
6
7use crate::engine::functions::FunctionConfig;
8use datalogic_rs::Logic;
9use serde::Deserialize;
10use serde_json::Value;
11use std::sync::Arc;
12
13/// A single processing unit within a workflow (also known as an Action in rules-engine terminology).
14///
15/// Tasks execute functions with optional conditions and error handling.
16/// They are processed sequentially within a workflow, allowing later tasks
17/// to depend on results from earlier ones.
18///
19/// # Example JSON Definition
20///
21/// ```json
22/// {
23///     "id": "validate_user",
24///     "name": "Validate User Data",
25///     "description": "Ensures user data meets requirements",
26///     "condition": {">=": [{"var": "data.order.total"}, 1000]},
27///     "function": {
28///         "name": "validation",
29///         "input": { "rules": [...] }
30///     },
31///     "continue_on_error": false
32/// }
33/// ```
34#[derive(Clone, Debug, Deserialize)]
35pub struct Task {
36    /// Unique identifier for the task within the workflow.
37    pub id: String,
38
39    /// Engine-internal: `Arc<str>` mirror of `id`, populated by
40    /// `LogicCompiler::compile_workflows`. Audit-trail emission clones this
41    /// instead of allocating a fresh `Arc<str>`. Public for crate-internal
42    /// access from the compiler and tests; not part of the stable API.
43    #[doc(hidden)]
44    #[serde(skip)]
45    pub id_arc: Arc<str>,
46
47    /// Human-readable name for the task.
48    pub name: String,
49
50    /// Optional description explaining what the task does.
51    pub description: Option<String>,
52
53    /// JSONLogic condition that determines if the task should execute.
54    /// Conditions can access any context field (`data`, `metadata`, `temp_data`).
55    /// Defaults to `true` (always execute).
56    #[serde(default = "default_condition")]
57    pub condition: Value,
58
59    /// Engine-internal: pre-compiled JSONLogic for `condition`, populated by
60    /// `LogicCompiler`. `None` is treated as "always run" by the executor.
61    /// Not part of the stable API.
62    #[doc(hidden)]
63    #[serde(skip)]
64    pub compiled_condition: Option<Arc<Logic>>,
65
66    /// The function configuration specifying what operation to perform.
67    /// Can be a built-in function (map, validation) or a custom function.
68    pub function: FunctionConfig,
69
70    /// Whether to continue workflow execution if this task fails.
71    /// When `true`, errors are recorded but don't stop the workflow.
72    /// Defaults to `false`.
73    #[serde(default)]
74    pub continue_on_error: bool,
75}
76
77impl Task {
78    /// Create a task (action) with default settings.
79    ///
80    /// This is a convenience constructor for the IFTTT-style rules engine pattern,
81    /// creating an action that always executes (condition defaults to `true`).
82    ///
83    /// # Arguments
84    /// * `id` - Unique identifier for the action
85    /// * `name` - Human-readable name
86    /// * `function` - The function configuration to execute
87    pub fn action(id: &str, name: &str, function: FunctionConfig) -> Self {
88        Task {
89            id: id.to_string(),
90            id_arc: Arc::from(id),
91            name: name.to_string(),
92            description: None,
93            condition: Value::Bool(true),
94            compiled_condition: None,
95            function,
96            continue_on_error: false,
97        }
98    }
99}
100
101/// Returns the default condition value (always true).
102fn default_condition() -> Value {
103    Value::Bool(true)
104}