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
5.4 KiB
5.4 KiB
OSIRIS Refactoring Complete! 🎉
Summary
Successfully refactored OSIRIS with:
- ✅ Builder Pattern for
OsirisContext - ✅ Type Registry for custom struct registration
- ✅ Engine Module moved to
rhaimodule - ✅ 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:
- Registry maps collection → type
- Single
save()function looks up the type - Deserializes JSON to the correct Rust struct
- Calls
store.put()with typed object - 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 typeOsirisContextBuilder- Builder for contextsOsirisInstance- Alias for backward compatibilityContextManager- Multi-tenant managerPrivilege,Member- Access control typesOsirisEngineConfig- Engine configurationcreate_osiris_engine()- Engine creation functionsregister_context_api()- Register context API in engine
From osiris::store:
TypeRegistry- Type registry for custom structsGenericStore- Generic storage layerObject,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! 🚀