mirror of
https://github.com/gorules/zen.git
synced 2026-10-05 08:02:28 +00:00
99 lines
2.6 KiB
Rust
99 lines
2.6 KiB
Rust
use std::fmt::{Debug, Formatter};
|
|
use std::future::Future;
|
|
use std::pin::Pin;
|
|
use std::sync::Arc;
|
|
|
|
use napi::anyhow::anyhow;
|
|
use napi::bindgen_prelude::{Buffer, Promise};
|
|
use napi::threadsafe_function::ThreadsafeFunction;
|
|
use napi::{Either, Status};
|
|
|
|
use zen_engine::loader::{
|
|
DecisionLoader as DecisionLoaderTrait, LoaderError, LoaderResponse, LoaderResult,
|
|
};
|
|
use zen_engine::model::DecisionContent;
|
|
|
|
use crate::content::ZenDecisionContent;
|
|
|
|
pub(crate) type LoaderTsfn = Arc<
|
|
ThreadsafeFunction<
|
|
String,
|
|
Promise<Option<Either<Buffer, &'static ZenDecisionContent>>>,
|
|
String,
|
|
Status,
|
|
false,
|
|
true,
|
|
>,
|
|
>;
|
|
|
|
#[derive(Default)]
|
|
pub(crate) struct DecisionLoader {
|
|
function: Option<LoaderTsfn>,
|
|
}
|
|
|
|
impl Debug for DecisionLoader {
|
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
|
write!(f, "DecisionLoader")
|
|
}
|
|
}
|
|
|
|
impl DecisionLoader {
|
|
pub fn new(tsf: LoaderTsfn) -> Self {
|
|
Self {
|
|
function: Some(tsf),
|
|
}
|
|
}
|
|
|
|
pub async fn get_key(&self, key: &str) -> LoaderResult<Arc<DecisionContent>> {
|
|
let Some(function) = &self.function else {
|
|
return Err(LoaderError::Internal {
|
|
key: key.to_string(),
|
|
source: anyhow!("Loader is undefined"),
|
|
}
|
|
.into());
|
|
};
|
|
|
|
let promise: Promise<Option<Either<Buffer, &ZenDecisionContent>>> = function
|
|
.clone()
|
|
.call_async(key.to_string())
|
|
.await
|
|
.map_err(|e| LoaderError::Internal {
|
|
key: key.to_string(),
|
|
source: anyhow!(e.reason.clone()),
|
|
})?;
|
|
|
|
let result = promise.await.map_err(|e| LoaderError::Internal {
|
|
key: key.to_string(),
|
|
source: anyhow!(e.reason.clone()),
|
|
})?;
|
|
|
|
let Some(buffer) = result else {
|
|
return Err(LoaderError::NotFound(key.to_string()).into());
|
|
};
|
|
|
|
let decision_content = match buffer {
|
|
Either::A(buf) => Arc::new(serde_json::from_slice(buf.as_ref()).map_err(|e| {
|
|
LoaderError::Internal {
|
|
key: key.to_string(),
|
|
source: e.into(),
|
|
}
|
|
})?),
|
|
Either::B(dc) => dc.inner.clone(),
|
|
};
|
|
|
|
Ok(decision_content)
|
|
}
|
|
}
|
|
|
|
impl DecisionLoaderTrait for DecisionLoader {
|
|
fn load<'a>(
|
|
&'a self,
|
|
key: &'a str,
|
|
) -> Pin<Box<dyn Future<Output = LoaderResponse> + 'a + Send>> {
|
|
Box::pin(async move {
|
|
let decision_content = self.get_key(key).await?;
|
|
Ok(decision_content)
|
|
})
|
|
}
|
|
}
|