mf_engine/handler/function_v1/
mod.rs

1use std::time::{Duration, Instant};
2
3use crate::handler::function_v1::script::Script;
4use crate::handler::node::{NodeRequest, NodeResponse, NodeResult};
5use crate::model::{DecisionNodeKind, FunctionNodeContent};
6use anyhow::anyhow;
7use rquickjs::Runtime;
8use serde_json::json;
9
10pub(crate) mod runtime;
11mod script;
12
13pub struct FunctionHandler {
14    trace: bool,
15    runtime: Runtime,
16}
17
18static MAX_DURATION: Duration = Duration::from_millis(500);
19
20impl FunctionHandler {
21    pub fn new(
22        trace: bool,
23        runtime: Runtime,
24    ) -> Self {
25        Self { trace, runtime }
26    }
27
28    pub async fn handle(
29        &self,
30        request: NodeRequest,
31    ) -> NodeResult {
32        let content = match &request.node.kind {
33            DecisionNodeKind::FunctionNode { content } => match content {
34                FunctionNodeContent::Version1(content) => Ok(content),
35                _ => Err(anyhow!("Unexpected node type")),
36            },
37            _ => Err(anyhow!("Unexpected node type")),
38        }?;
39
40        let start = Instant::now();
41        let interrupt_handler =
42            Box::new(move || start.elapsed() > MAX_DURATION);
43        self.runtime.set_interrupt_handler(Some(interrupt_handler));
44
45        let mut script = Script::new(self.runtime.clone());
46        let result_response = script.call(content, &request.input).await;
47
48        self.runtime.set_interrupt_handler(None);
49
50        let response = result_response?;
51        Ok(NodeResponse {
52            output: response.output,
53            trace_data: self.trace.then(|| json!({ "log": response.log })),
54        })
55    }
56}