mirror of
https://github.com/gorules/zen.git
synced 2026-10-06 08:02:18 +00:00
* feat: function v2 * expose evaluate * remove async trait, add caching * fix naming * add reverse compatibility * add http module * update impl * resolve issues with reqwest * fix * fix * fix ssl * remove unused deps * fix: tests * fix
77 lines
2.2 KiB
Rust
77 lines
2.2 KiB
Rust
use std::future::Future;
|
|
use std::sync::Arc;
|
|
|
|
use napi::anyhow::anyhow;
|
|
use napi::bindgen_prelude::{Buffer, Promise};
|
|
use napi::threadsafe_function::{ErrorStrategy, ThreadsafeFunction};
|
|
use napi::Either;
|
|
|
|
use zen_engine::loader::{
|
|
DecisionLoader as DecisionLoaderTrait, LoaderError, LoaderResponse, LoaderResult,
|
|
};
|
|
use zen_engine::model::DecisionContent;
|
|
|
|
use crate::content::ZenDecisionContent;
|
|
|
|
#[derive(Default)]
|
|
pub(crate) struct DecisionLoader {
|
|
function: Option<ThreadsafeFunction<String, ErrorStrategy::Fatal>>,
|
|
}
|
|
|
|
impl DecisionLoader {
|
|
pub fn new(tsf: ThreadsafeFunction<String, ErrorStrategy::Fatal>) -> napi::Result<Self> {
|
|
Ok(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),
|
|
})?;
|
|
|
|
let result = promise.await.map_err(|e| LoaderError::Internal {
|
|
key: key.to_string(),
|
|
source: anyhow!(e.reason),
|
|
})?;
|
|
|
|
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) -> impl Future<Output = LoaderResponse> + 'a {
|
|
async move {
|
|
let decision_content = self.get_key(key).await?;
|
|
Ok(decision_content)
|
|
}
|
|
}
|
|
}
|