incurs_codemode/
engine.rs1use std::sync::Arc;
2
3use async_trait::async_trait;
4use serde::{Deserialize, Serialize};
5use serde_json::Value;
6
7use crate::{ConnectorDescription, DispatchResponse, DispatchSession, StepResponse};
8
9#[derive(Debug, Clone, Serialize, Deserialize)]
11pub struct ExecuteResult {
12 pub result: Option<Value>,
14 pub error: Option<String>,
16 pub logs: Vec<String>,
18}
19
20#[derive(Debug, Clone, Serialize, Deserialize)]
22#[serde(tag = "kind", rename_all = "snake_case")]
23pub enum DispatchRequest {
24 Call {
26 execution_id: String,
28 seq: u64,
30 connector: String,
32 method: String,
34 arguments: Value,
36 },
37 BeginStep {
39 execution_id: String,
41 seq: u64,
43 name: String,
45 },
46 RecordStep {
48 execution_id: String,
50 seq: u64,
52 result: Value,
54 },
55}
56
57#[async_trait(?Send)]
62pub trait CodeExecutor {
63 async fn execute(
65 &self,
66 code: &str,
67 connectors: &[ConnectorDescription],
68 execution_id: &str,
69 host: Arc<ExecutionHost>,
70 ) -> Result<ExecuteResult, String>;
71}
72
73pub trait Clock: Send + Sync {
75 fn now_ms(&self) -> u64;
77}
78
79#[derive(Debug, Clone, Copy, Default)]
81pub struct SystemClock;
82
83impl Clock for SystemClock {
84 fn now_ms(&self) -> u64 {
85 std::time::SystemTime::now()
86 .duration_since(std::time::UNIX_EPOCH)
87 .unwrap_or_default()
88 .as_millis() as u64
89 }
90}
91
92pub struct ExecutionHost {
94 session: Arc<DispatchSession>,
95 clock: Arc<dyn Clock>,
96}
97
98impl ExecutionHost {
99 pub(crate) fn new(session: Arc<DispatchSession>, clock: Arc<dyn Clock>) -> Self {
100 Self { session, clock }
101 }
102
103 pub async fn call(
105 &self,
106 seq: u64,
107 connector: &str,
108 method: &str,
109 arguments: Value,
110 ) -> DispatchResponse {
111 self.session
112 .call_at(seq, connector, method, arguments, self.clock.now_ms())
113 .await
114 }
115
116 pub async fn begin_step(&self, seq: u64, name: &str) -> Result<StepResponse, String> {
118 self.session
119 .begin_step_at(seq, name, self.clock.now_ms())
120 .await
121 .map_err(|error| error.to_string())
122 }
123
124 pub async fn record_step(&self, seq: u64, result: Value) -> Result<(), String> {
126 self.session
127 .record_step(seq, result, self.clock.now_ms())
128 .await
129 .map_err(|error| error.to_string())
130 }
131}