fraiseql_functions/runtime/mod.rs
1//! Function runtime trait and implementations.
2
3#[cfg(feature = "runtime-wasm")]
4pub mod wasm;
5
6#[cfg(feature = "runtime-deno")]
7pub mod deno;
8
9use std::future::Future;
10
11use async_trait::async_trait;
12use fraiseql_error::Result;
13
14use crate::{
15 HostContext,
16 types::{EventPayload, FunctionModule, FunctionResult, ResourceLimits},
17};
18
19/// Trait for function execution backends (WASM, Deno, etc.).
20///
21/// Implementors provide the ability to load and execute function modules
22/// with resource limits enforced. This trait uses native async for zero-cost
23/// abstraction on hot paths.
24pub trait FunctionRuntime: Send + Sync {
25 /// Execute a function module with the given event and host context.
26 ///
27 /// # Errors
28 ///
29 /// Returns `Err` if:
30 /// - The module cannot be loaded or parsed
31 /// - Execution raises an error (runtime error, timeout, memory limit exceeded)
32 /// - The host context raises an error
33 fn invoke<H>(
34 &self,
35 module: &FunctionModule,
36 event: EventPayload,
37 host: &H,
38 limits: ResourceLimits,
39 ) -> impl Future<Output = Result<FunctionResult>> + Send
40 where
41 H: HostContext + ?Sized;
42
43 /// Get the list of file extensions this runtime supports.
44 fn supported_extensions(&self) -> &[&str];
45
46 /// Check if this runtime supports hot-reloading modules without restart.
47 fn supports_hot_reload(&self) -> bool;
48
49 /// Get the name of this runtime (e.g., "wasm", "deno").
50 fn name(&self) -> &str;
51}
52
53/// Type alias for a boxable function runtime (with static lifetime bounds).
54/// Used for dynamic dispatch where concrete types aren't known at compile time.
55pub type BoxedFunctionRuntime = Box<dyn FunctionRuntime + Send + Sync>;
56
57/// Object-safe variant of `FunctionRuntime` for dynamic dispatch.
58///
59/// This trait has the same semantic methods but without generic parameters,
60/// making it suitable for `Arc<dyn SendFunctionRuntime>`. The `invoke_raw`
61/// method uses a [`NoopHostContext`](crate::NoopHostContext) internally.
62#[async_trait]
63pub trait SendFunctionRuntime: Send + Sync {
64 /// Execute a function module with the given event and resource limits.
65 ///
66 /// Uses [`NoopHostContext`](crate::NoopHostContext) — callers that need
67 /// host-bridge functionality should use [`FunctionRuntime::invoke`] with
68 /// a concrete host context instead.
69 ///
70 /// # Errors
71 ///
72 /// Returns `Err` if the module cannot be loaded, or execution fails.
73 async fn invoke_raw(
74 &self,
75 module: &FunctionModule,
76 event: EventPayload,
77 limits: ResourceLimits,
78 ) -> Result<FunctionResult>;
79
80 /// Get the list of file extensions this runtime supports.
81 fn supported_extensions(&self) -> &[&str];
82
83 /// Check if this runtime supports hot-reloading modules without restart.
84 fn supports_hot_reload(&self) -> bool;
85
86 /// Get the name of this runtime (e.g., "wasm", "deno").
87 fn name(&self) -> &str;
88}