Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions Cargo.toml
Original file line numberDiff line numberDiff line change
Expand Up@@ -8,12 +8,12 @@ edition = "2024"

[workspace.dependencies]
async-trait = "0.1.89"
code0-flow = { version = "0.0.43" }
tucana = { version = "0.0.80" }
code0-flow = { version = "0.0.44" }
tucana = { version = "0.0.81" }
tokio = { version = "1.44.1", features = ["rt-multi-thread", "signal"] }
log = "0.4.27"
opentelemetry = { version = "0.32.0", features = ["metrics"] }
lupus = "0.0.3"
lupus = "0.0.4"
futures-lite = "2.6.0"
rand = "0.10.0"
base64 = "0.23.0"
Expand Down
19 changes: 13 additions & 6 deletions crates/taurus-bench/benches/engine_execution.rs
Original file line numberDiff line numberDiff line change
Expand Up@@ -12,9 +12,9 @@ use criterion::{BenchmarkId, Criterion, criterion_group, criterion_main};
use std::collections::HashMap;
use taurus_core::runtime::engine::ExecutionEngine;
use tucana::shared::{
ListValue, NodeFunction, NodeParameter, NodeValue, ReferenceValue, Struct, SubFlow, Value,
node_value, reference_value, reference_value::Target, sub_flow::ExecutionReference,
value::Kind,
ListValue, LiteralValue, NodeFunction, NodeParameter, NodeValue, ReferenceValue, Struct,
SubFlow, Value, node_value, reference_value, reference_value::Target,
sub_flow::ExecutionReference, value::Kind,
};

fn int_value(value: i64) -> Value {
Expand All@@ -26,7 +26,10 @@ fn literal_param(runtime_parameter_id: &str, value: Value) -> NodeParameter {
database_id: 0,
runtime_parameter_id: runtime_parameter_id.to_string(),
value: Some(NodeValue {
value: Some(node_value::Value::LiteralValue(value)),
value: Some(node_value::Value::LiteralValue(LiteralValue {
value: Some(value),
references: Vec::new(),
})),
}),
cast: None,
}
Expand DownExpand Up@@ -150,7 +153,9 @@ fn bench_chain(c: &mut Criterion) {
&size,
|b, _| {
let engine = ExecutionEngine::new();
b.iter(|| engine.execute_graph("bench", start, nodes.clone(), None, None, with_trace));
b.iter(|| {
engine.execute_graph("bench", start, nodes.clone(), None, None, with_trace)
});
},
);
}
Expand All@@ -168,7 +173,9 @@ fn bench_array_map(c: &mut Criterion) {
&size,
|b, _| {
let engine = ExecutionEngine::new();
b.iter(|| engine.execute_graph("bench", start, nodes.clone(), None, None, with_trace));
b.iter(|| {
engine.execute_graph("bench", start, nodes.clone(), None, None, with_trace)
});
},
);
}
Expand Down
12 changes: 9 additions & 3 deletions crates/taurus-bench/examples/profile_workload.rs
Original file line numberDiff line numberDiff line change
Expand Up@@ -5,7 +5,9 @@

use std::collections::HashMap;
use taurus_core::runtime::engine::ExecutionEngine;
use tucana::shared::{NodeFunction, NodeParameter, NodeValue, ReferenceValue, node_value};
use tucana::shared::{
LiteralValue, NodeFunction, NodeParameter, NodeValue, ReferenceValue, node_value,
};

fn int_value(value: i64) -> tucana::shared::Value {
taurus_core::value::value_from_i64(value)
Expand All@@ -16,7 +18,10 @@ fn literal_param(runtime_parameter_id: &str, value: tucana::shared::Value) -> No
database_id: 0,
runtime_parameter_id: runtime_parameter_id.to_string(),
value: Some(NodeValue {
value: Some(node_value::Value::LiteralValue(value)),
value: Some(node_value::Value::LiteralValue(LiteralValue {
value: Some(value),
references: Vec::new(),
})),
}),
cast: None,
}
Expand DownExpand Up@@ -85,7 +90,8 @@ fn main() {

let mut total = HashMap::new();
for i in 0..iterations {
let (signal, _reason) = engine.execute_graph("bench", start, nodes.clone(), None, None, with_trace);
let (signal, _reason) =
engine.execute_graph("bench", start, nodes.clone(), None, None, with_trace);
total.insert(i, signal.exit_reason());
}
// Prevent the compiler from optimizing the loop away.
Expand Down
31 changes: 28 additions & 3 deletions crates/taurus-core/src/handler/argument.rs
Original file line numberDiff line numberDiff line change
Expand Up@@ -32,14 +32,18 @@ impl fmt::Debug for FunctionThunk {

#[derive(Clone)]
pub enum Thunk {
Node(i64),
Node {
node_id: i64,
input_schema: Option<Struct>,
output_schema: Option<Struct>,
},
Function(FunctionThunk),
}

impl fmt::Debug for Thunk {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Thunk::Node(node_id) => write!(f, "{}", node_id),
Thunk::Node { node_id, .. } => write!(f, "{}", node_id),
Thunk::Function(function) => function.fmt(f),
}
}
Expand All@@ -48,18 +52,39 @@ impl fmt::Debug for Thunk {
impl Thunk {
pub fn trace_target(&self) -> String {
match self {
Thunk::Node(node_id) => format!("node={}", node_id),
Thunk::Node { node_id, .. } => format!("node={}", node_id),
Thunk::Function(function) => format!("function={}", function.identifier),
}
}
}

/// A literal value template plus its named inline references (`${signature}`),
/// mirrored from `CompiledTemplate` at argument-build time so each reference
/// can be resolved (or, on the remote path, minted/forwarded) independently.
#[derive(Clone, Debug)]
pub struct TemplateArgument {
pub value: Value,
pub references: Vec<TemplateReferenceArgument>,
}

#[derive(Clone, Debug)]
pub struct TemplateReferenceArgument {
pub signature: String,
pub arg: Box<Argument>,
}

#[derive(Clone, Debug)]
pub enum Argument {
/// Eager value that can be consumed immediately by a handler.
Eval(Value),
/// Deferred execution handle, evaluated by calling `run(thunk)`.
Thunk(Thunk),
/// A literal with unresolved `${signature}` placeholders. Always
/// collapsed to `Eval` before a local handler runs (see
/// `EngineExecutor::resolve_local_templates`); preserved as-is on the
/// remote path so an action can interpolate itself (see
/// `EngineExecutor::resolve_remote_args`).
Template(TemplateArgument),
}

#[derive(Clone, Copy, Debug)]
Expand Down
69 changes: 52 additions & 17 deletions crates/taurus-core/src/runtime/engine.rs
Original file line numberDiff line numberDiff line change
Expand Up@@ -305,12 +305,13 @@ mod tests {
use async_trait::async_trait;
use std::sync::{Arc, Mutex};
use std::time::Duration;
use tucana::aquila::{ActionExecutionRequest, ActionNodeSubFlowValue, action_node_value};
use tucana::aquila::{
ActionExecutionRequest, ActionLiteralValue, ActionNodeSubFlowValue, action_node_value,
};
use tucana::shared::{
InputType, ListValue, NodeExecutionResult, NodeParameter, NodeValue, ReferenceValue,
Struct, SubFlow, SubFlowFunction, SubFlowSetting, Value, node_execution_result,
node_value, reference_value,
sub_flow::ExecutionReference,
InputType, ListValue, LiteralValue, NodeExecutionResult, NodeParameter, NodeValue,
ReferenceValue, Struct, SubFlow, SubFlowFunction, SubFlowSetting, Value,
node_execution_result, node_value, reference_value, sub_flow::ExecutionReference,
value::Kind,
};

Expand All@@ -319,7 +320,10 @@ mod tests {
database_id,
runtime_parameter_id: runtime_parameter_id.to_string(),
value: Some(NodeValue {
value: Some(node_value::Value::LiteralValue(value)),
value: Some(node_value::Value::LiteralValue(LiteralValue {
value: Some(value),
references: Vec::new(),
})),
}),
cast: None,
}
Expand DownExpand Up@@ -816,11 +820,17 @@ mod tests {
assert_eq!(first_parameters.len(), 2);
assert_eq!(
first_parameters[0].value,
Some(action_node_value::Value::LiteralValue(int_value(1)))
Some(action_node_value::Value::LiteralValue(ActionLiteralValue {
value: Some(int_value(1)),
references: Vec::new(),
}))
);
assert_eq!(
first_parameters[1].value,
Some(action_node_value::Value::LiteralValue(int_value(2)))
Some(action_node_value::Value::LiteralValue(ActionLiteralValue {
value: Some(int_value(2)),
references: Vec::new(),
}))
);

let function_results: Vec<_> = report
Expand DownExpand Up@@ -925,7 +935,8 @@ mod tests {
None,
);

let (signal, reason) = engine.execute_graph("test", 1, vec![filter_node], None, None, false);
let (signal, reason) =
engine.execute_graph("test", 1, vec![filter_node], None, None, false);

assert_eq!(reason, ExitReason::Success);
assert_eq!(
Expand DownExpand Up@@ -1218,7 +1229,8 @@ mod tests {
None,
);

let report = engine.execute_graph_report("test", 1, vec![value_node, add_node], None, None, false);
let report =
engine.execute_graph_report("test", 1, vec![value_node, add_node], None, None, false);

assert_eq!(report.exit_reason, ExitReason::Success);
assert_eq!(report.node_execution_results.len(), 2);
Expand DownExpand Up@@ -1260,7 +1272,8 @@ mod tests {
);
remote_node.definition_source = Some("remote-service".to_string());

let report = engine.execute_graph_report("test", 1, vec![remote_node], None, Some(&remote), false);
let report =
engine.execute_graph_report("test", 1, vec![remote_node], None, Some(&remote), false);

assert_eq!(report.exit_reason, ExitReason::Failure);
match report.signal {
Expand DownExpand Up@@ -1306,7 +1319,8 @@ mod tests {
);
remote_node.definition_source = Some("action.example".to_string());

let report = engine.execute_graph_report("test", 1, vec![remote_node], None, Some(&remote), false);
let report =
engine.execute_graph_report("test", 1, vec![remote_node], None, Some(&remote), false);

assert_eq!(report.exit_reason, ExitReason::Success);
assert_eq!(
Expand DownExpand Up@@ -1380,6 +1394,8 @@ mod tests {
{
if let Some(action_node_value::Value::SubFlow(ActionNodeSubFlowValue {
execution_identifier,
input_schema: _,
output_schema: _,
})) = &execution.request.parameters[0].value
{
*self
Expand DownExpand Up@@ -1462,6 +1478,8 @@ mod tests {
let execution_identifier = match &parameters[0].value {
Some(action_node_value::Value::SubFlow(ActionNodeSubFlowValue {
execution_identifier,
input_schema: _,
output_schema: _,
})) => {
assert!(
uuid::Uuid::parse_str(execution_identifier).is_ok(),
Expand All@@ -1480,7 +1498,10 @@ mod tests {
// The parent node's own remote call has resolved (successfully), so
// the registry entry it minted must already have been cleaned up.
assert!(
engine.sub_flow_registry.get(&execution_identifier).is_none(),
engine
.sub_flow_registry
.get(&execution_identifier)
.is_none(),
"registry entry should be removed once the parent call resolves"
);
}
Expand DownExpand Up@@ -1513,6 +1534,8 @@ mod tests {

if let Some(action_node_value::Value::SubFlow(ActionNodeSubFlowValue {
execution_identifier,
input_schema: _,
output_schema: _,
})) = execution
.request
.parameters
Expand DownExpand Up@@ -1711,8 +1734,14 @@ mod tests {
None,
);

let report =
engine.execute_graph_report("test", 1, vec![for_each_node, callback_node], None, None, false);
let report = engine.execute_graph_report(
"test",
1,
vec![for_each_node, callback_node],
None,
None,
false,
);

assert_eq!(report.exit_reason, ExitReason::Success);
assert_eq!(report.node_execution_results.len(), 4);
Expand DownExpand Up@@ -1796,8 +1825,14 @@ mod tests {
);
for_each_node.definition_source = Some("draco-draco-cron".to_string());

let report =
engine.execute_graph_report("test", 2, vec![value_node, for_each_node], None, None, false);
let report = engine.execute_graph_report(
"test",
2,
vec![value_node, for_each_node],
None,
None,
false,
);

assert_eq!(report.exit_reason, ExitReason::Success);
assert_eq!(expect_success(report.signal), response_value);
Expand Down
Loading