1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
//! # moduforge-rules-engine
//!
//! moduforge-rules-engine 是一个对业务友好的开源业务规则引擎(BRE),用于根据 GoRules JSON 决策模型(JDM)标准执行决策模型。
//!
//! # 使用方法
//!
//! 要使用 Noop(默认)加载器执行简单决策,您可以使用以下代码:
//!
//! ```rust
//! use serde_json::json;
//! use mf_rules_engine::DecisionEngine;
//! use mf_rules_engine::model::DecisionContent;
//!
//! async fn evaluate() {
//! let decision_content: DecisionContent = serde_json::from_str(include_str!("jdm_graph.json")).unwrap();
//! let engine = DecisionEngine::default();
//! let decision = engine.create_decision(decision_content.into());
//!
//! let result = decision.evaluate(&json!({ "input": 12 })).await;
//! }
//! ```
//!
//! 另外,您也可以使用 `Decision::from` 函数间接创建决策,而无需构建引擎。
//!
//! # 加载器
//!
//! 对于更高级的用例,当您需要加载多个决策并使用图时,您可以使用以下预制的加载器之一:
//! - FilesystemLoader - 使用给定路径作为根目录,尝试基于相对路径加载决策
//! - MemoryLoader - 作为 HashMap(键值存储)工作
//! - ClosureLoader - 允许定义简单的异步回调函数,该函数接收键作为参数并返回 `Arc<DecisionContent>` 实例
//! - NoopLoader - (默认)无法加载决策,允许使用 create_decision(主要用于跨语言统一 API)
//!
//! ## 文件系统加载器
//!
//! 假设您有一个位于 /app/decisions 下的决策模型文件夹(.json 文件),您可以按以下方式使用 FilesystemLoader:
//!
//! ```rust
//! use serde_json::json;
//! use mf_rules_engine::DecisionEngine;
//! use mf_rules_engine::loader::{FilesystemLoader, FilesystemLoaderOptions};
//!
//! async fn evaluate() {
//! let engine = DecisionEngine::new(FilesystemLoader::new(FilesystemLoaderOptions {
//! keep_in_memory: true, // 可选,保持在内存中以提高性能
//! root: "/app/decisions"
//! }));
//!
//! let context = json!({ "customer": { "joinedAt": "2022-01-01" } });
//! // 如果您计划多次使用它,可以缓存 JDM 以获得轻微的性能提升
//! // 在绑定(其他语言)的情况下,这种提升会更大
//! {
//! let promotion_decision = engine.get_decision("commercial/promotion.json").await.unwrap();
//! let result = promotion_decision.evaluate(&context).await.unwrap();
//! }
//!
//! // 或者按需加载
//! {
//! let result = engine.evaluate("commercial/promotion.json", &context).await.unwrap();
//! }
//! }
//!
//!
//! ```
//!
//! ## 自定义加载器
//! 您可以通过实现 `DecisionLoader` trait 为 zen 引擎创建自定义加载器。
//! 以下是 MemoryLoader 的实现示例:
//! ```rust
//! use std::collections::HashMap;
//! use std::sync::{Arc, RwLock};
//! use zen_engine::loader::{DecisionLoader, LoaderError, LoaderResponse};
//! use zen_engine::model::DecisionContent;
//!
//! #[derive(Debug, Default)]
//! pub struct MemoryLoader {
//! memory_refs: RwLock<HashMap<String, Arc<DecisionContent>>>,
//! }
//!
//! impl MemoryLoader {
//! pub fn add<K, D>(&self, key: K, content: D)
//! where
//! K: Into<String>,
//! D: Into<DecisionContent>,
//! {
//! let mut mref = self.memory_refs.write().unwrap();
//! mref.insert(key.into(), Arc::new(content.into()));
//! }
//!
//! pub fn get<K>(&self, key: K) -> Option<Arc<DecisionContent>>
//! where
//! K: AsRef<str>,
//! {
//! let mref = self.memory_refs.read().unwrap();
//! mref.get(key.as_ref()).map(|r| r.clone())
//! }
//!
//! pub fn remove<K>(&self, key: K) -> bool
//! where
//! K: AsRef<str>,
//! {
//! let mut mref = self.memory_refs.write().unwrap();
//! mref.remove(key.as_ref()).is_some()
//! }
//! }
//!
//! impl DecisionLoader for MemoryLoader {
//! fn load<'a>(&'a self, key: &'a str) -> impl Future<Output = LoaderResponse> + 'a {
//! async move {
//! self.get(&key)
//! .ok_or_else(|| LoaderError::NotFound(key.to_string()).into())
//! }
//! }
//! ```
pub use ZEN_CONFIG;
pub use Decision;
pub use ;
pub use EvaluationError;
pub use DecisionGraphResponse;
pub use DecisionGraphTrace;
pub use DecisionGraphValidationError;
pub use NodeError;
pub use Variable;