rhailib/src/engine/docs/ARCHITECTURE.md
2025-06-27 12:09:50 +03:00

8.8 KiB

Architecture of the rhailib_engine Crate

The rhailib_engine crate serves as the central Rhai scripting engine for the heromodels ecosystem. It provides a unified interface for creating, configuring, and executing Rhai scripts with access to all business domain modules through a feature-based architecture.

Core Architecture

The engine acts as an orchestration layer that brings together the DSL modules and provides execution utilities:

graph TD
    A[rhailib_engine] --> B[Engine Creation]
    A --> C[Script Execution]
    A --> D[Mock Database]
    A --> E[Feature Management]
    
    B --> B1[create_heromodels_engine]
    B --> B2[Engine Configuration]
    B --> B3[DSL Registration]
    
    C --> C1[eval_script]
    C --> C2[eval_file]
    C --> C3[compile_script]
    C --> C4[run_ast]
    
    D --> D1[create_mock_db]
    D --> D2[seed_mock_db]
    D --> D3[Domain Data Seeding]
    
    E --> E1[calendar]
    E --> E2[finance]
    E --> E3[flow]
    E --> E4[legal]
    E --> E5[projects]
    E --> E6[biz]
    
    B3 --> F[rhailib_dsl]
    F --> G[All Domain Modules]

Core Components

1. Engine Factory (create_heromodels_engine)

The primary entry point for creating a fully configured Rhai engine:

pub fn create_heromodels_engine() -> Engine

Responsibilities:

  • Creates a new Rhai engine instance
  • Configures engine limits and settings
  • Registers all available DSL modules
  • Returns a ready-to-use engine

Configuration Settings:

  • Expression Depth: 128 levels for both expressions and functions
  • String Size Limit: 10 MB maximum string size
  • Array Size Limit: 10,000 elements maximum
  • Map Size Limit: 10,000 key-value pairs maximum

2. Script Execution Utilities

Direct Script Evaluation

pub fn eval_script(engine: &Engine, script: &str) -> Result<Dynamic, Box<EvalAltResult>>

Executes Rhai script strings directly with immediate results.

File-Based Script Execution

pub fn eval_file(engine: &Engine, file_path: &Path) -> Result<Dynamic, Box<EvalAltResult>>

Loads and executes Rhai scripts from filesystem with proper error handling.

Compiled Script Execution

pub fn compile_script(engine: &Engine, script: &str) -> Result<AST, Box<EvalAltResult>>
pub fn run_ast(engine: &Engine, ast: &AST, scope: &mut Scope) -> Result<Dynamic, Box<EvalAltResult>>

Provides compilation and execution of scripts for performance optimization.

3. Mock Database System

Database Creation

pub fn create_mock_db() -> Arc<OurDB>

Creates an in-memory database instance for testing and examples.

Data Seeding

pub fn seed_mock_db(db: Arc<OurDB>)

Populates the mock database with representative data across all domains.

Feature-Based Architecture

The engine uses Cargo features to control which domain modules are included:

Available Features

  • calendar (default): Calendar and event management
  • finance (default): Financial accounts, assets, and marketplace
  • flow: Workflow and approval processes
  • legal: Contract and legal document management
  • projects: Project and task management
  • biz: Business operations and entities

Feature Integration Pattern

#[cfg(feature = "calendar")]
use heromodels::models::calendar::*;

#[cfg(feature = "finance")]
use heromodels::models::finance::*;

This allows for:

  • Selective Compilation: Only include needed functionality
  • Reduced Binary Size: Exclude unused domain modules
  • Modular Deployment: Different configurations for different use cases

Mock Database Architecture

Database Structure

The mock database provides a complete testing environment:

graph LR
    A[Mock Database] --> B[Calendar Data]
    A --> C[Finance Data]
    A --> D[Flow Data]
    A --> E[Legal Data]
    A --> F[Projects Data]
    
    B --> B1[Calendars]
    B --> B2[Events]
    B --> B3[Attendees]
    
    C --> C1[Accounts]
    C --> C2[Assets - ERC20/ERC721]
    C --> C3[Marketplace Listings]
    
    D --> D1[Flows]
    D --> D2[Flow Steps]
    D --> D3[Signature Requirements]
    
    E --> E1[Contracts]
    E --> E2[Contract Revisions]
    E --> E3[Contract Signers]
    
    F --> F1[Projects]
    F --> F2[Project Members]
    F --> F3[Project Tags]

Seeding Strategy

Each domain has its own seeding function that creates realistic test data:

Calendar Seeding

  • Creates work calendars with descriptions
  • Adds team meetings with attendees
  • Sets up recurring events

Finance Seeding

  • Creates demo trading accounts
  • Generates ERC20 tokens and ERC721 NFTs
  • Sets up marketplace listings with metadata

Flow Seeding (Feature-Gated)

  • Creates document approval workflows
  • Defines multi-step approval processes
  • Sets up signature requirements
  • Creates service agreements
  • Adds contract revisions and versions
  • Defines contract signers and roles

Projects Seeding (Feature-Gated)

  • Creates project instances with status tracking
  • Assigns team members and priorities
  • Adds project tags and categorization

Error Handling Architecture

Comprehensive Error Propagation

Result<Dynamic, Box<EvalAltResult>>

All functions return proper Rhai error types that include:

  • Script Compilation Errors: Syntax and parsing issues
  • Runtime Errors: Execution failures and exceptions
  • File System Errors: File reading and path resolution issues
  • Database Errors: Mock database operation failures

Error Context Enhancement

File operations include enhanced error context:

Err(Box::new(EvalAltResult::ErrorSystem(
    format!("Failed to read script file: {}", file_path.display()),
    Box::new(io_err),
)))

Performance Considerations

Engine Configuration

Optimized settings for production use:

  • Memory Limits: Prevent runaway script execution
  • Depth Limits: Avoid stack overflow from deep recursion
  • Size Limits: Control memory usage for large data structures

Compilation Strategy

  • AST Caching: Compile once, execute multiple times
  • Scope Management: Efficient variable scope handling
  • Module Registration: One-time registration at engine creation

Mock Database Performance

  • In-Memory Storage: Fast access for testing scenarios
  • Temporary Directories: Automatic cleanup after use
  • Lazy Loading: Data seeded only when needed

Integration Patterns

Script Development Workflow

// 1. Create engine with all modules
let engine = create_heromodels_engine();

// 2. Execute business logic scripts
let result = eval_script(&engine, r#"
    let company = new_company()
        .name("Tech Startup")
        .business_type("startup");
    save_company(company)
"#)?;

// 3. Handle results and errors
match result {
    Ok(value) => println!("Success: {:?}", value),
    Err(error) => eprintln!("Error: {}", error),
}

Testing Integration

// 1. Create mock database
let db = create_mock_db();
seed_mock_db(db.clone());

// 2. Create engine
let engine = create_heromodels_engine();

// 3. Test scripts against seeded data
let script = r#"
    let calendars = list_calendars();
    calendars.len()
"#;
let count = eval_script(&engine, script)?;

File-Based Script Execution

// Execute scripts from files
let result = eval_file(&engine, Path::new("scripts/business_logic.rhai"))?;

Deployment Configurations

Minimal Configuration

[dependencies]
rhailib_engine = { version = "0.1.0", default-features = false, features = ["calendar"] }

Full Configuration

[dependencies]
rhailib_engine = { version = "0.1.0", features = ["calendar", "finance", "flow", "legal", "projects", "biz"] }

Custom Configuration

[dependencies]
rhailib_engine = { version = "0.1.0", default-features = false, features = ["finance", "biz"] }

Security Considerations

Script Execution Limits

  • Resource Limits: Prevent resource exhaustion attacks
  • Execution Time: Configurable timeouts for long-running scripts
  • Memory Bounds: Controlled memory allocation

Database Access

  • Mock Environment: Safe testing without production data exposure
  • Temporary Storage: Automatic cleanup prevents data persistence
  • Isolated Execution: Each test run gets fresh database state

Extensibility

Adding New Domains

  1. Create new feature flag in Cargo.toml
  2. Add conditional imports for new models
  3. Implement seeding function for test data
  4. Register with DSL module system

Custom Engine Configuration

let mut engine = Engine::new();
// Custom configuration
engine.set_max_expr_depths(256, 256);
// Register specific modules
rhailib_dsl::register_dsl_modules(&mut engine);

This architecture provides a robust, feature-rich foundation for Rhai script execution while maintaining flexibility, performance, and security.