use std::collections::HashMap;
use std::sync::Arc;
use tokio::sync::RwLock;
use crate::{Rule, RuleResult, RulesError, Result};
use crate::context::ExecutionContext;
use crate::conditions::ConditionEvaluator;
use crate::actions::ActionExecutor;
pub struct RuleEngine {
rules: Arc<RwLock<HashMap<String, Rule>>>,
condition_evaluator: ConditionEvaluator,
action_executor: ActionExecutor,
}
impl RuleEngine {
pub fn new() -> Self {
Self {
rules: Arc::new(RwLock::new(HashMap::new())),
condition_evaluator: ConditionEvaluator::new(),
action_executor: ActionExecutor::new(),
}
}
pub async fn add_rule(&mut self, rule: Rule) -> Result<()> {
rule.is_valid()?;
self.rules.write().await.insert(rule.id.clone(), rule);
Ok(())
}
pub async fn execute_rule(&self, rule: &Rule, context: &mut ExecutionContext) -> Result<RuleResult> {
if !rule.enabled {
return Ok(RuleResult::Skipped);
}
for condition in &rule.conditions {
if !self.condition_evaluator.evaluate_condition(condition, context).await? {
return Ok(RuleResult::Skipped);
}
}
for action in &rule.actions {
self.action_executor.execute_action(action, context).await?;
}
Ok(RuleResult::Allow)
}
pub async fn evaluate_condition(&self, condition: &crate::RuleCondition, context: &ExecutionContext) -> Result<bool> {
self.condition_evaluator.evaluate_condition(condition, context).await
}
pub async fn execute_action(&self, action: &crate::RuleAction, context: &mut ExecutionContext) -> Result<()> {
self.action_executor.execute_action(action, context).await
}
}
impl Default for RuleEngine {
fn default() -> Self {
Self::new()
}
}