mirror of
https://github.com/gorules/zen.git
synced 2026-10-04 00:02:18 +00:00
fix: nodejs add dispose method (#413)
This commit is contained in:
@@ -11,6 +11,7 @@ crate-type = ["cdylib"]
|
||||
[dependencies]
|
||||
ahash = { workspace = true }
|
||||
napi = { version = "3", features = ["serde-json", "error_anyhow", "tokio_rt"] }
|
||||
napi-sys = "3"
|
||||
napi-derive = "3"
|
||||
tokio-util = { workspace = true, features = ["rt"] }
|
||||
serde_json = { workspace = true }
|
||||
|
||||
Vendored
+4
-3
@@ -3,7 +3,7 @@
|
||||
export declare class ZenDecision {
|
||||
constructor()
|
||||
evaluate(context: any, opts?: ZenEvaluateOptions | undefined | null): Promise<ZenEngineResponse>
|
||||
safeEvaluate(context: any, opts?: ZenEvaluateOptions | undefined | null): Promise<SafeResult<ZenEngineResponse>>
|
||||
safeEvaluate(context: any, opts?: ZenEvaluateOptions | undefined | null): { success: true, data: ZenEngineResponse } | { success: false; error: any; }
|
||||
validate(): void
|
||||
}
|
||||
|
||||
@@ -17,8 +17,9 @@ export declare class ZenEngine {
|
||||
evaluate(key: string, context: any, opts?: ZenEvaluateOptions | undefined | null): Promise<ZenEngineResponse>
|
||||
createDecision(content: ZenDecisionContent | Buffer | object): ZenDecision
|
||||
getDecision(key: string): Promise<ZenDecision>
|
||||
safeEvaluate(key: string, context: any, opts?: ZenEvaluateOptions | undefined | null): Promise<SafeResult<ZenEngineResponse>>
|
||||
safeGetDecision(key: string): Promise<SafeResult<ZenDecision>>
|
||||
safeEvaluate(key: string, context: any, opts?: ZenEvaluateOptions | undefined | null): { success: true, data: ZenEngineResponse } | { success: false; error: any; }
|
||||
safeGetDecision(key: string): { success: true, data: ZenDecision } | { success: false; error: any; }
|
||||
dispose(): void
|
||||
}
|
||||
|
||||
export declare class ZenEngineHandlerRequest {
|
||||
|
||||
@@ -10,7 +10,7 @@ use zen_engine::nodes::custom::{CustomNodeAdapter, CustomNodeRequest};
|
||||
use zen_engine::nodes::{NodeError, NodeResponse, NodeResult};
|
||||
use zen_engine::Variable;
|
||||
|
||||
type CustomNodeTsfn = Arc<
|
||||
pub(crate) type CustomNodeTsfn = Arc<
|
||||
ThreadsafeFunction<
|
||||
ZenEngineHandlerRequest,
|
||||
Promise<ZenEngineHandlerResponse>,
|
||||
|
||||
@@ -46,7 +46,9 @@ impl ZenDecision {
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
#[napi(ts_return_type = "Promise<SafeResult<ZenEngineResponse>>")]
|
||||
#[napi(
|
||||
ts_return_type = "{ success: true, data: ZenEngineResponse } | { success: false; error: any; }"
|
||||
)]
|
||||
pub async fn safe_evaluate(
|
||||
&self,
|
||||
context: Value,
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
use napi::check_status;
|
||||
use napi::threadsafe_function::ThreadsafeFunctionHandle;
|
||||
|
||||
pub trait DisposeThreadsafeHandler {
|
||||
fn dispose(&self) -> napi::Result<()>;
|
||||
}
|
||||
|
||||
impl DisposeThreadsafeHandler for ThreadsafeFunctionHandle {
|
||||
fn dispose(&self) -> napi::Result<()> {
|
||||
self.with_write_aborted(|mut aborted_guard| {
|
||||
if !*aborted_guard {
|
||||
check_status!(unsafe {
|
||||
napi_sys::napi_release_threadsafe_function(
|
||||
self.get_raw(),
|
||||
napi_sys::ThreadsafeFunctionReleaseMode::abort,
|
||||
)
|
||||
})?;
|
||||
*aborted_guard = true;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -10,21 +10,27 @@ use napi::{Env, JsValue, Unknown, ValueType};
|
||||
use napi_derive::napi;
|
||||
use serde_json::Value;
|
||||
|
||||
use zen_engine::model::DecisionContent;
|
||||
use zen_engine::{DecisionEngine, EvaluationSerializedOptions, EvaluationTraceKind};
|
||||
|
||||
use crate::content::ZenDecisionContent;
|
||||
use crate::custom_node::CustomNode;
|
||||
use crate::custom_node::{CustomNode, CustomNodeTsfn};
|
||||
use crate::decision::ZenDecision;
|
||||
use crate::http_handler::{NodeHttpHandler, ZenHttpHandlerRequest, ZenHttpHandlerResponse};
|
||||
use crate::loader::DecisionLoader;
|
||||
use crate::dispose::DisposeThreadsafeHandler;
|
||||
use crate::http_handler::{
|
||||
HttpHandlerTsfn, NodeHttpHandler, ZenHttpHandlerRequest, ZenHttpHandlerResponse,
|
||||
};
|
||||
use crate::loader::{DecisionLoader, LoaderTsfn};
|
||||
use crate::mt::spawn_worker;
|
||||
use crate::safe_result::SafeResult;
|
||||
use crate::types::{ZenEngineHandlerRequest, ZenEngineHandlerResponse};
|
||||
use zen_engine::model::DecisionContent;
|
||||
use zen_engine::{DecisionEngine, EvaluationSerializedOptions, EvaluationTraceKind};
|
||||
|
||||
#[napi]
|
||||
pub struct ZenEngine {
|
||||
graph: Arc<DecisionEngine>,
|
||||
|
||||
custom_node_tsfn: Option<CustomNodeTsfn>,
|
||||
loader_tsfn: Option<LoaderTsfn>,
|
||||
http_handler_tsfn: Option<HttpHandlerTsfn>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
@@ -124,9 +130,17 @@ impl ZenEngine {
|
||||
Arc::new(CustomNode::default()),
|
||||
)
|
||||
.into(),
|
||||
|
||||
loader_tsfn: None,
|
||||
http_handler_tsfn: None,
|
||||
custom_node_tsfn: None,
|
||||
});
|
||||
};
|
||||
|
||||
let mut loader_tsfn_opt: Option<LoaderTsfn> = None;
|
||||
let mut http_handler_tsfn_opt: Option<HttpHandlerTsfn> = None;
|
||||
let mut custom_node_tsfn_opt: Option<CustomNodeTsfn> = None;
|
||||
|
||||
let loader = match opts.loader {
|
||||
None => DecisionLoader::default(),
|
||||
Some(l) => {
|
||||
@@ -137,7 +151,9 @@ impl ZenEngine {
|
||||
.weak()
|
||||
.build()?;
|
||||
|
||||
DecisionLoader::new(Arc::new(loader_tsfn))
|
||||
let arc_loader_tsfn = Arc::new(loader_tsfn);
|
||||
loader_tsfn_opt = Some(arc_loader_tsfn.clone());
|
||||
DecisionLoader::new(arc_loader_tsfn)
|
||||
}
|
||||
};
|
||||
|
||||
@@ -151,7 +167,9 @@ impl ZenEngine {
|
||||
.weak()
|
||||
.build()?;
|
||||
|
||||
CustomNode::new(Arc::new(custom_tfsn))
|
||||
let arc_custom_node = Arc::new(custom_tfsn);
|
||||
custom_node_tsfn_opt = Some(arc_custom_node.clone());
|
||||
CustomNode::new(arc_custom_node)
|
||||
}
|
||||
};
|
||||
|
||||
@@ -164,12 +182,18 @@ impl ZenEngine {
|
||||
.weak()
|
||||
.build()?;
|
||||
|
||||
let arc_http_handler_tsfn = Arc::new(http_tsfn);
|
||||
http_handler_tsfn_opt = Some(arc_http_handler_tsfn.clone());
|
||||
decision_engine = decision_engine
|
||||
.with_http_handler(Some(Arc::new(NodeHttpHandler::new(Arc::new(http_tsfn)))));
|
||||
.with_http_handler(Some(Arc::new(NodeHttpHandler::new(arc_http_handler_tsfn))));
|
||||
}
|
||||
|
||||
Ok(Self {
|
||||
graph: Arc::new(decision_engine),
|
||||
|
||||
loader_tsfn: loader_tsfn_opt,
|
||||
http_handler_tsfn: http_handler_tsfn_opt,
|
||||
custom_node_tsfn: custom_node_tsfn_opt,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -228,7 +252,9 @@ impl ZenEngine {
|
||||
Ok(ZenDecision::from(decision))
|
||||
}
|
||||
|
||||
#[napi(ts_return_type = "Promise<SafeResult<ZenEngineResponse>>")]
|
||||
#[napi(
|
||||
ts_return_type = "{ success: true, data: ZenEngineResponse } | { success: false; error: any; }"
|
||||
)]
|
||||
pub async fn safe_evaluate(
|
||||
&self,
|
||||
key: String,
|
||||
@@ -238,8 +264,25 @@ impl ZenEngine {
|
||||
self.evaluate(key, context, opts).await.into()
|
||||
}
|
||||
|
||||
#[napi(ts_return_type = "Promise<SafeResult<ZenDecision>>")]
|
||||
#[napi(
|
||||
ts_return_type = "{ success: true, data: ZenDecision } | { success: false; error: any; }"
|
||||
)]
|
||||
pub async fn safe_get_decision(&self, key: String) -> SafeResult<ZenDecision> {
|
||||
self.get_decision(key).await.into()
|
||||
}
|
||||
|
||||
#[napi]
|
||||
pub fn dispose(&self) {
|
||||
if let Some(loader_tsfn) = &self.loader_tsfn {
|
||||
let _ = loader_tsfn.handle.dispose();
|
||||
}
|
||||
|
||||
if let Some(http_handler_tsfn) = &self.http_handler_tsfn {
|
||||
let _ = http_handler_tsfn.handle.dispose();
|
||||
}
|
||||
|
||||
if let Some(custom_node) = &self.custom_node_tsfn {
|
||||
let _ = custom_node.handle.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ use zen_engine::nodes::http_handler::{
|
||||
HttpHandlerResponse as EngineHttpHandlerResponse,
|
||||
};
|
||||
|
||||
type HttpHandlerTsfn = Arc<
|
||||
pub(crate) type HttpHandlerTsfn = Arc<
|
||||
ThreadsafeFunction<
|
||||
ZenHttpHandlerRequest,
|
||||
Promise<ZenHttpHandlerResponse>,
|
||||
|
||||
@@ -2,6 +2,7 @@ mod config;
|
||||
mod content;
|
||||
mod custom_node;
|
||||
mod decision;
|
||||
mod dispose;
|
||||
mod engine;
|
||||
mod expression;
|
||||
mod http_handler;
|
||||
|
||||
@@ -15,7 +15,7 @@ use zen_engine::model::DecisionContent;
|
||||
|
||||
use crate::content::ZenDecisionContent;
|
||||
|
||||
type LoaderTsfn = Arc<
|
||||
pub(crate) type LoaderTsfn = Arc<
|
||||
ThreadsafeFunction<
|
||||
String,
|
||||
Promise<Option<Either<Buffer, &'static ZenDecisionContent>>>,
|
||||
|
||||
Reference in New Issue
Block a user