Files
osiris/REFACTORING_COMPLETE.md
Timur Gordon e04012c8c0 Refactor Rhai integration with context-based execution and type registry
Major Changes:
- Moved Rhai support from rhai_support/ to rhai/ module
- Implemented context-based execution with signatory access control
- Added TypeRegistry for dynamic type registration and object creation
- Refactored engine to use context (Vec<String>) instead of instance
- Removed old runner binary (moved to runner_rust crate)

Rhai Module:
- engine.rs: Core Rhai engine with context-based get_context()
- functions.rs: Rhai function bindings (create_note, create_event, etc.)
- mod.rs: Module exports and organization

Store Improvements:
- TypeRegistry for registering object types and creators
- Generic store uses type registry for dynamic object creation
- Improved error handling and type safety

Documentation:
- RHAI_REFACTOR_COMPLETE.md: Refactoring details
- SIGNATORY_ACCESS_CONTROL.md: Context-based access control
- TYPE_REGISTRY_DESIGN.md: Type registry architecture
- REFACTORING_COMPLETE.md: Overall refactoring summary
- TESTS_COMPLETE.md: Testing documentation

Build Status:  Compiles successfully with minor warnings
2025-10-28 03:33:39 +01:00

5.4 KiB

OSIRIS Refactoring Complete! 🎉

Summary

Successfully refactored OSIRIS with:

  1. Builder Pattern for OsirisContext
  2. Type Registry for custom struct registration
  3. Engine Module moved to rhai module
  4. Simplified Runner using the new architecture

1. Builder Pattern

Before:

OsirisContext::new_with_registry(name, owner, url, db_id, registry)

After:

let ctx = OsirisContext::builder()
    .name("my_context")
    .owner("user_123")
    .herodb_url("redis://localhost:6379")
    .db_id(1)
    .registry(registry)  // Optional
    .build()?;

Benefits:

  • Fluent, readable API
  • Optional parameters
  • Type-safe construction
  • Backward compatible with OsirisContext::new()

2. Type Registry

Architecture:

// 1. Create registry
let registry = TypeRegistry::new();

// 2. Register types (one line per type!)
registry.register_type::<Resident>("residents")?;
registry.register_type::<Company>("companies")?;
registry.register_type::<Invoice>("invoices")?;

// 3. Create context with registry
let ctx = OsirisContext::builder()
    .name("zdfz")
    .owner("admin")
    .herodb_url(url)
    .db_id(1)
    .registry(Arc::new(registry))
    .build()?;

// 4. Save uses the correct type automatically!
ctx.save("residents", "id123", resident_data)?;  // Uses Resident type
ctx.save("companies", "id456", company_data)?;   // Uses Company type

How It Works:

  1. Registry maps collection → type
  2. Single save() function looks up the type
  3. Deserializes JSON to the correct Rust struct
  4. Calls store.put() with typed object
  5. Proper indexing happens via index_keys() method

No callbacks, no multiple functions - just ONE save function! 🎯


3. Engine Module

Moved from:

src/bin/runner/engine.rs

To:

src/rhai/engine.rs

New API:

use osiris::rhai::{
    OsirisEngineConfig,
    create_osiris_engine,
    create_osiris_engine_with_config,
    create_osiris_engine,
};

// Simple engine
let (engine, scope) = create_osiris_engine("owner", "redis://localhost:6379", 1)?;

// With config
let mut config = OsirisEngineConfig::new();
config.add_context("ctx1", "owner1", "redis://localhost:6379", 1);
config.add_context("ctx2", "owner2", "redis://localhost:6379", 2);
let (engine, scope) = create_osiris_engine_with_config(config)?;

// With context manager (dynamic contexts)
let engine = create_osiris_engine("redis://localhost:6379", 1)?;

4. Simplified Runner

New Structure:

src/bin/runner.rs  (single file!)

Usage:

# Run a script
cargo run --bin runner --features rhai-support -- runner1 \
  --script "ctx.save('residents', 'id123', data);"

# With custom contexts
cargo run --bin runner --features rhai-support -- runner1 \
  --instance freezone:redis://localhost:6379:1 \
  --instance backup:redis://localhost:6379:2 \
  --script "freezone.save('residents', 'id123', data);"

File Structure

osiris/src/
├── rhai/
│   ├── mod.rs           # Exports
│   ├── instance.rs      # OsirisContext + Builder + ContextManager
│   └── engine.rs        # Engine creation functions
├── store/
│   ├── mod.rs
│   ├── generic_store.rs
│   └── type_registry.rs # Type registry for custom structs
└── bin/
    └── runner.rs        # Simplified runner binary

Exports

From osiris::rhai:

  • OsirisContext - Main context type
  • OsirisContextBuilder - Builder for contexts
  • OsirisInstance - Alias for backward compatibility
  • ContextManager - Multi-tenant manager
  • Privilege, Member - Access control types
  • OsirisEngineConfig - Engine configuration
  • create_osiris_engine() - Engine creation functions
  • register_context_api() - Register context API in engine

From osiris::store:

  • TypeRegistry - Type registry for custom structs
  • GenericStore - Generic storage layer
  • Object, Storable - Traits

Usage in ZDFZ API

use osiris::rhai::{OsirisContext, OsirisEngineConfig, create_osiris_engine_with_config};
use osiris::store::TypeRegistry;
use std::sync::Arc;

// 1. Create type registry
let registry = TypeRegistry::new();
registry.register_type::<DigitalResident>("residents")?;
registry.register_type::<FreezoneCompany>("companies")?;
registry.register_type::<Invoice>("invoices")?;
let registry = Arc::new(registry);

// 2. Create engine config
let mut config = OsirisEngineConfig::new();
config.add_context("zdfz", "admin", "redis://localhost:6379", 1);

// 3. Create engine
let (mut engine, scope) = create_osiris_engine_with_config(config)?;

// 4. Register ZDFZ DSL functions
register_resident_api(&mut engine);
register_company_api(&mut engine);
register_invoice_api(&mut engine);

// 5. Run scripts!
engine.eval_with_scope(&mut scope, r#"
    let resident = create_resident(#{
        email: "test@example.com",
        first_name: "John"
    });
    
    zdfz.save("residents", resident.id, resident);
"#)?;

Benefits

Clean API - Builder pattern for context creation Type-Safe - Registry ensures correct types are used Flexible - Applications register their own types Proper Indexing - Each type's index_keys() is called Organized - Engine in rhai module where it belongs Simple Runner - Single file, uses library code


Status: All refactoring complete and ready for use! 🚀