#[cfg(test)]
mod tests;
use std::{collections::HashMap, sync::Arc};
use fraiseql_error::Result;
use crate::{
HostContext,
runtime::FunctionRuntime,
types::{EventPayload, FunctionModule, FunctionResult, ResourceLimits, RuntimeType},
};
pub struct FunctionObserver {
runtimes: HashMap<RuntimeType, Arc<dyn std::any::Any + Send + Sync>>,
}
impl FunctionObserver {
#[must_use]
pub fn new() -> Self {
Self {
runtimes: HashMap::new(),
}
}
pub fn register_runtime<R: FunctionRuntime + 'static>(
&mut self,
runtime_type: RuntimeType,
runtime: R,
) {
self.runtimes.insert(runtime_type, Arc::new(runtime));
}
pub async fn invoke<H>(
&self,
module: &FunctionModule,
#[allow(unused_variables)] event: EventPayload,
#[allow(unused_variables)] host: &H,
#[allow(unused_variables)] limits: ResourceLimits,
) -> Result<FunctionResult>
where
H: HostContext + ?Sized,
{
#[allow(unused_variables)] let runtime_box = self.runtimes.get(&module.runtime).ok_or_else(|| {
fraiseql_error::FraiseQLError::Unsupported {
message: format!("No runtime registered for {:?}", module.runtime),
}
})?;
#[allow(unreachable_patterns)] match module.runtime {
RuntimeType::Wasm => {
#[cfg(feature = "runtime-wasm")]
{
let runtime = runtime_box
.downcast_ref::<crate::runtime::wasm::WasmRuntime>()
.ok_or_else(|| fraiseql_error::FraiseQLError::Unsupported {
message: "Invalid WASM runtime".to_string(),
})?;
runtime.invoke(module, event, host, limits).await
}
#[cfg(not(feature = "runtime-wasm"))]
{
Err(fraiseql_error::FraiseQLError::Unsupported {
message: "WASM runtime not enabled".to_string(),
})
}
},
RuntimeType::Deno => {
#[cfg(feature = "runtime-deno")]
{
let runtime = runtime_box
.downcast_ref::<crate::runtime::deno::DenoRuntime>()
.ok_or_else(|| fraiseql_error::FraiseQLError::Unsupported {
message: "Invalid Deno runtime".to_string(),
})?;
runtime.invoke(module, event, host, limits).await
}
#[cfg(not(feature = "runtime-deno"))]
{
Err(fraiseql_error::FraiseQLError::Unsupported {
message: "Deno runtime not enabled".to_string(),
})
}
},
}
}
#[must_use]
pub fn find_after_mutation_triggers(
&self,
registry: &crate::triggers::registry::TriggerRegistry,
event: &crate::triggers::mutation::EntityEvent,
) -> Vec<crate::triggers::mutation::AfterMutationTrigger> {
registry.after_mutation_triggers.find(&event.entity, event.event_kind)
}
}
impl Default for FunctionObserver {
fn default() -> Self {
Self::new()
}
}