noetl_executor/runtime.rs
1//! Per-execution runtime context shared between sources, dispatch, and
2//! event emission.
3//!
4//! `ExecutionContext` is the durable carrier for one playbook execution.
5//! Both the CLI's local-mode runner and the worker's NATS daemon
6//! construct one of these per invocation; the dispatch layer reads from
7//! it to resolve credentials, look up rendered step input, and emit
8//! events into the configured sink.
9//!
10//! This module deliberately starts minimal — the skeleton commits the
11//! shape, R-1.2 (extraction PR) fills in the concrete fields by porting
12//! them from `repos/cli/src/playbook_runner.rs`.
13
14use anyhow::Result;
15use std::collections::HashMap;
16use std::sync::Arc;
17
18/// Identifies one playbook execution end-to-end.
19///
20/// R-1.2 PR-2a: aliased to `i64` to match the Python `noetl.event` /
21/// `noetl.command` table columns (bigint), the CLI's
22/// `BridgeContext.execution_id` (i64), `noetl_tools::context::
23/// ExecutionContext.execution_id` (i64), and the worker's
24/// `CommandNotification.execution_id` (i64). The `pub struct
25/// ExecutionId(pub String)` newtype in 0.1.x was a placeholder while
26/// nothing crossed the boundary; R-1.2 starts cross-binary work so
27/// the type alignment matters.
28pub type ExecutionId = i64;
29
30/// Trait for resolving keychain credential aliases at step-execution
31/// time. Mirrors the Python-side `noetl.core.credential_refs`
32/// resolution flow; see noetl/noetl wiki page `credential-resolution-flow`.
33#[async_trait::async_trait]
34pub trait CredentialResolver: Send + Sync {
35 /// Resolve `alias` (e.g. `"duffel"`) to its concrete credential
36 /// envelope. Implementations consult the NoETL keychain (worker
37 /// path) or the CLI's local keychain cache (CLI path).
38 async fn resolve(&self, alias: &str) -> Result<serde_json::Value>;
39}
40
41/// Carries everything one execution needs. Cheap to clone via `Arc`s
42/// on the inner heavy fields.
43#[derive(Clone)]
44pub struct ExecutionContext {
45 pub execution_id: ExecutionId,
46 pub credentials: Arc<dyn CredentialResolver>,
47 /// Step-level results accumulated during execution. Used by the
48 /// template layer to render `{{ step_name.result }}` references.
49 pub step_results: Arc<tokio::sync::RwLock<HashMap<String, serde_json::Value>>>,
50 /// Workload payload (`workload:` block from the YAML, plus any
51 /// `--set` overrides from the CLI or runtime defaults from NATS).
52 pub workload: Arc<serde_json::Value>,
53}
54
55impl ExecutionContext {
56 /// Construct a fresh context. R-1.2 will add a builder that
57 /// reads the workload from the YAML's `workload:` block and
58 /// applies CLI overrides.
59 pub fn new(
60 execution_id: ExecutionId,
61 credentials: Arc<dyn CredentialResolver>,
62 workload: serde_json::Value,
63 ) -> Self {
64 Self {
65 execution_id,
66 credentials,
67 step_results: Arc::new(tokio::sync::RwLock::new(HashMap::new())),
68 workload: Arc::new(workload),
69 }
70 }
71}