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
This commit is contained in:
221
REFACTORING_COMPLETE.md
Normal file
221
REFACTORING_COMPLETE.md
Normal file
@@ -0,0 +1,221 @@
|
||||
# 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:
|
||||
```rust
|
||||
OsirisContext::new_with_registry(name, owner, url, db_id, registry)
|
||||
```
|
||||
|
||||
### After:
|
||||
```rust
|
||||
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:
|
||||
```rust
|
||||
// 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:
|
||||
```rust
|
||||
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:
|
||||
```bash
|
||||
# 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
|
||||
|
||||
```rust
|
||||
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! 🚀
|
||||
Reference in New Issue
Block a user