Skip to main content

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