Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
117 changes: 39 additions & 78 deletions core/engine/src/model/decision_content.rs
Original file line number Diff line number Diff line change
@@ -1,49 +1,28 @@
use ahash::{HashMap, HashMapExt};
use serde::{Deserialize, Serialize};
use std::sync::Arc;
use zen_expression::compiler::Opcode;
use zen_expression::{ExpressionKind, Isolate};
use zen_expression::{ExpressionKind, Isolate, OpcodeCache};
use zen_types::decision::{DecisionEdge, DecisionNode, DecisionNodeKind};

#[derive(Clone, Debug, Eq, PartialEq, Hash)]
pub struct CompilationKey {
pub kind: ExpressionKind,
pub source: Arc<str>,
}
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize, Default)]
#[serde(rename_all = "camelCase")]
pub struct DecisionContent {
pub nodes: Vec<Arc<DecisionNode>>,
pub edges: Vec<Arc<DecisionEdge>>,

#[serde(skip)]
pub compiled_cache: Option<Arc<HashMap<CompilationKey, Vec<Opcode>>>>,
pub compiled_cache: Option<Arc<OpcodeCache>>,
}

impl DecisionContent {
pub fn compile(&mut self) {
let mut compiled_cache: HashMap<CompilationKey, Vec<Opcode>> = HashMap::new();
let mut isolate = Isolate::new();
let mut sources: Vec<(Arc<str>, ExpressionKind)> = Vec::new();

for node in &self.nodes {
match &node.kind {
DecisionNodeKind::ExpressionNode { content } => {
for expression in content.expressions.iter() {
if expression.key.is_empty() || expression.value.is_empty() {
continue;
}

let key = CompilationKey {
kind: ExpressionKind::Standard,
source: Arc::clone(&expression.value),
};

if compiled_cache.contains_key(&key) {
continue;
}

if let Ok(comp_expression) = isolate.compile_standard(&expression.value) {
compiled_cache.insert(key, comp_expression.bytecode().to_vec());
for expr in content.expressions.iter() {
if !expr.key.is_empty() && !expr.value.is_empty() {
sources.push((expr.value.clone(), ExpressionKind::Standard));
}
}
}
Expand All @@ -54,71 +33,53 @@ impl DecisionContent {
continue;
};

if rule_value.is_empty() {
continue;
}

match &input.field {
None => {
let key = CompilationKey {
kind: ExpressionKind::Standard,
source: Arc::clone(rule_value),
};

if !compiled_cache.contains_key(&key) {
if let Ok(comp_expression) =
isolate.compile_standard(rule_value)
{
compiled_cache
.insert(key, comp_expression.bytecode().to_vec());
}
}
}
Some(_field) => {
let key = CompilationKey {
kind: ExpressionKind::Unary,
source: Arc::clone(rule_value),
};
let kind = if input.field.is_some() {
ExpressionKind::Unary
} else {
ExpressionKind::Standard
};

if !compiled_cache.contains_key(&key) {
if let Ok(comp_expression) =
isolate.compile_unary(rule_value)
{
compiled_cache
.insert(key, comp_expression.bytecode().to_vec());
}
}
}
}
sources.push((rule_value.clone(), kind));
}

for output in content.outputs.iter() {
let Some(rule_value) = rule.get(&output.id) else {
continue;
};

if rule_value.is_empty() {
continue;
}

let key = CompilationKey {
kind: ExpressionKind::Standard,
source: Arc::clone(rule_value),
};

if !compiled_cache.contains_key(&key) {
if let Ok(comp_expression) = isolate.compile_standard(rule_value) {
compiled_cache.insert(key, comp_expression.bytecode().to_vec());
}
}
sources.push((rule_value.clone(), ExpressionKind::Standard));
}
}
}

_ => {}
}
}

self.compiled_cache.replace(Arc::new(compiled_cache));
let mut cache: OpcodeCache = OpcodeCache::new();
let mut isolate = Isolate::new();

for (source, kind) in &sources {
let map = match kind {
ExpressionKind::Standard => &mut cache.standard,
ExpressionKind::Unary => &mut cache.unary,
};
if map.contains_key(source) {
continue;
}

let result = match kind {
ExpressionKind::Standard => isolate
.compile_standard(source)
.map(|e| e.bytecode().to_vec()),
ExpressionKind::Unary => {
isolate.compile_unary(source).map(|e| e.bytecode().to_vec())
}
};
if let Ok(bytecode) = result {
map.insert(source.clone(), Arc::from(bytecode));
}
}

self.compiled_cache.replace(Arc::new(cache));
}
}
1 change: 0 additions & 1 deletion core/engine/src/model/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
pub use zen_types::decision::*;
mod decision_content;
pub use decision_content::CompilationKey;
pub use decision_content::DecisionContent;
62 changes: 9 additions & 53 deletions core/engine/src/nodes/decision_table/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use crate::model::CompilationKey;
use crate::nodes::definition::NodeHandler;
use crate::nodes::result::NodeResult;
use crate::nodes::{NodeContext, NodeResponse};
Expand All @@ -8,7 +7,7 @@ use std::ops::Deref;
use std::rc::Rc;
use std::sync::Arc;
use zen_expression::variable::ToVariable;
use zen_expression::{ExpressionKind, Isolate};
use zen_expression::Isolate;
use zen_types::decision::{DecisionTableContent, DecisionTableHitPolicy, TransformAttributes};
use zen_types::variable::Variable;
#[derive(Debug, Clone)]
Expand Down Expand Up @@ -39,8 +38,8 @@ impl NodeHandler for DecisionTableNodeHandler {

impl DecisionTableNodeHandler {
fn handle_first_hit(&self, ctx: DecisionTableContext) -> NodeResult {
let mut isolate = Isolate::new();
isolate.set_environment(ctx.input.depth_clone(1));
let mut isolate = Isolate::with_environment(ctx.input.depth_clone(1))
.with_cache(ctx.extensions.compiled_cache.clone());

for (index, rule) in ctx.node.rules.iter().enumerate() {
if let Some(result) = self.evaluate_row(&ctx, rule, &mut isolate) {
Expand Down Expand Up @@ -72,10 +71,10 @@ impl DecisionTableNodeHandler {
}

fn handle_collect(&self, ctx: DecisionTableContext) -> NodeResult {
let mut isolate = Isolate::new();
let mut outputs = Vec::new();
let mut traces = Vec::new();
isolate.set_environment(ctx.input.depth_clone(1));
let mut isolate = Isolate::with_environment(ctx.input.depth_clone(1))
.with_cache(ctx.extensions.compiled_cache.clone());

for (index, rule) in ctx.node.rules.iter().enumerate() {
if let Some(result) = self.evaluate_row(&ctx, rule, &mut isolate) {
Expand Down Expand Up @@ -121,44 +120,15 @@ impl DecisionTableNodeHandler {

match &input.field {
None => {
let key = CompilationKey {
kind: ExpressionKind::Standard,
source: Arc::from(rule_value.clone()),
};
let result: Variable;
if let Some(codes) = ctx
.extensions
.compiled_cache
.as_ref()
.and_then(|cc| cc.get(&key))
{
result = isolate.run_compiled(codes).ok()?;
} else {
result = isolate.run_standard(rule_value).ok()?;
}
let result = isolate.run_standard(rule_value).ok()?;
if !result.as_bool().unwrap_or(false) {
return None;
}
}
Some(field) => {
isolate.set_reference(&field).ok()?;
let key = CompilationKey {
kind: ExpressionKind::Unary,
source: Arc::from(rule_value.clone()),
};
if let Some(codes) = ctx
.extensions
.compiled_cache
.as_ref()
.and_then(|cc| cc.get(&key))
{
if !isolate.run_unary_compiled(codes).ok()? {
return None;
}
} else {
if !isolate.run_unary(&rule_value).ok()? {
return None;
}
if !isolate.run_unary(rule_value).ok()? {
return None;
}
}
}
Expand All @@ -171,21 +141,7 @@ impl DecisionTableNodeHandler {
continue;
}

let key = CompilationKey {
kind: ExpressionKind::Standard,
source: Arc::from(rule_value.clone()),
};
let res: Variable;
if let Some(codes) = ctx
.extensions
.compiled_cache
.as_ref()
.and_then(|cc| cc.get(&key))
{
res = isolate.run_compiled(codes).ok()?;
} else {
res = isolate.run_standard(rule_value).ok()?;
}
let res = isolate.run_standard(rule_value).ok()?;
outputs.dot_insert(output.field.deref(), res);
}

Expand Down
29 changes: 8 additions & 21 deletions core/engine/src/nodes/expression/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use crate::model::CompilationKey;
use crate::model::ExpressionNodeContent;
use crate::nodes::result::NodeResult;
use ahash::HashMap;
Expand All @@ -7,7 +6,7 @@ use std::rc::Rc;
use crate::nodes::context::{NodeContext, NodeContextExt};
use crate::nodes::definition::NodeHandler;
use zen_expression::variable::{ToVariable, Variable};
use zen_expression::{ExpressionKind, Isolate};
use zen_expression::Isolate;
use zen_types::decision::TransformAttributes;

#[derive(Debug, Clone)]
Expand All @@ -29,31 +28,19 @@ impl NodeHandler for ExpressionNodeHandler {

async fn handle(&self, ctx: NodeContext<Self::NodeData, Self::TraceData>) -> NodeResult {
let result = Variable::empty_object();
let mut isolate = Isolate::new();
isolate.set_environment(ctx.input.depth_clone(1));
let mut isolate = Isolate::with_environment(ctx.input.depth_clone(1))
.with_cache(ctx.extensions.compiled_cache.clone());

for expression in ctx.node.expressions.iter() {
if expression.key.is_empty() || expression.value.is_empty() {
continue;
}
let key = CompilationKey {
kind: ExpressionKind::Standard,
source: expression.value.clone(),
};
let value;
match ctx
.extensions
.compiled_cache
.as_ref()
.and_then(|cc| cc.get(&key))
{
Some(codes) => value = isolate.run_compiled(codes.as_slice()),
None => value = isolate.run_standard(&expression.value),
}

let value = value.with_node_context(&ctx, |_| {
format!(r#"Failed to evaluate expression: "{}""#, &expression.value)
})?;
let value = isolate
.run_standard(&expression.value)
.with_node_context(&ctx, |_| {
format!(r#"Failed to evaluate expression: "{}""#, &expression.value)
})?;
ctx.trace(|trace| {
trace.insert(
Rc::from(&*expression.key),
Expand Down
6 changes: 2 additions & 4 deletions core/engine/src/nodes/extensions.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,15 @@
use crate::loader::{DynamicLoader, NoopLoader};
use crate::model::CompilationKey;
use crate::nodes::custom::{DynamicCustomNode, NoopCustomNode};
use crate::nodes::function::http_handler::DynamicHttpHandler;
use crate::nodes::function::v2::function::{Function, FunctionConfig};
use crate::nodes::function::v2::module::console::ConsoleListener;
use crate::nodes::function::v2::module::http::listener::HttpListener;
use crate::nodes::function::v2::module::zen::ZenListener;
use crate::nodes::validator_cache::ValidatorCache;
use ahash::HashMap;
use anyhow::Context;
use std::cell::OnceCell;
use std::sync::Arc;
use zen_expression::compiler::Opcode;
use zen_expression::OpcodeCache;

/// This is created on every graph evaluation
#[derive(Debug, Clone)]
Expand All @@ -21,7 +19,7 @@ pub struct NodeHandlerExtensions {
pub(crate) loader: DynamicLoader,
pub(crate) custom_node: DynamicCustomNode,
pub(crate) http_handler: DynamicHttpHandler,
pub(crate) compiled_cache: Option<Arc<HashMap<CompilationKey, Vec<Opcode>>>>,
pub(crate) compiled_cache: Option<Arc<OpcodeCache>>,
}

impl Default for NodeHandlerExtensions {
Expand Down
Loading
Loading