Update osiris dependency to use osiris-core package

This commit is contained in:
Timur Gordon
2025-11-04 13:09:13 +01:00
parent 2ea963ddf5
commit 4158d02f3d
14 changed files with 1282 additions and 1723 deletions

View File

@@ -2,7 +2,7 @@ use runner_rust::{spawn_sync_runner, script_mode::execute_script_mode};
use clap::Parser;
use log::{error, info};
use tokio::sync::mpsc;
use osiris::rhai::create_osiris_engine;
use osiris::create_osiris_engine;
#[derive(Parser, Debug)]
#[command(author, version, about, long_about = None)]
@@ -41,7 +41,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
&args.runner_id,
args.redis_url,
std::time::Duration::from_secs(300), // Default timeout for OSIS
move || create_osiris_engine(&redis_url, base_db_id)
move || create_osiris_engine()
.expect("Failed to create OSIRIS engine"),
).await;
@@ -78,7 +78,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
args.runner_id.clone(),
args.redis_url,
shutdown_rx,
move || create_osiris_engine(&redis_url, base_db_id)
move || create_osiris_engine()
.expect("Failed to create OSIRIS engine"),
);
@@ -101,3 +101,15 @@ async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
Ok(())
}
/// Example: Run a Rhai script with OSIRIS support
pub fn run_osiris_script(
script: &str,
) -> Result<(), Box<dyn std::error::Error>> {
let engine = create_osiris_engine()?;
engine.run(script)?;
Ok(())
}

View File

@@ -71,3 +71,128 @@ pub fn create_sal_engine() -> Engine {
pub fn create_shared_sal_engine() -> Arc<Engine> {
EngineFactory::global().get_engine()
}
use std::sync::{Arc, OnceLock};
// Re-export common Rhai types for convenience
pub use rhai::{Array, Dynamic, Engine, EvalAltResult, Map};
// Re-export specific functions from sal-os package
pub use sal_os::rhai::{
delete,
// Download functions
download,
download_install,
// File system functions
exist,
file_size,
find_dir,
find_dirs,
find_file,
find_files,
mkdir,
register_os_module,
rsync,
};
// Re-export Redis client module registration function
pub use sal_redisclient::rhai::register_redisclient_module;
// Re-export PostgreSQL client module registration function
pub use sal_postgresclient::rhai::register_postgresclient_module;
pub use sal_process::rhai::{
kill,
process_get,
process_list,
register_process_module,
// Run functions
// Process management functions
which,
};
// Re-export virt functions from sal-virt package
pub use sal_virt::rhai::nerdctl::{
nerdctl_copy,
nerdctl_exec,
nerdctl_image_build,
nerdctl_image_commit,
nerdctl_image_pull,
nerdctl_image_push,
nerdctl_image_remove,
nerdctl_image_tag,
// Image functions
nerdctl_images,
nerdctl_list,
nerdctl_remove,
// Container functions
nerdctl_run,
nerdctl_run_with_name,
nerdctl_run_with_port,
nerdctl_stop,
};
pub use sal_virt::rhai::{
bah_new, register_bah_module, register_nerdctl_module, register_rfs_module,
};
pub use sal_git::rhai::register_git_module;
pub use sal_git::{GitRepo, GitTree};
pub use sal_zinit_client::rhai::register_zinit_module;
pub use sal_mycelium::rhai::register_mycelium_module;
pub use sal_text::rhai::register_text_module;
pub use sal_net::rhai::register_net_module;
pub use sal_kubernetes::rhai::register_kubernetes_module;
pub use sal_kubernetes::KubernetesManager;
pub use sal_os::rhai::copy as os_copy;
pub use sal_hetzner::rhai::register_hetzner_module;
/// Engine factory for creating and sharing Rhai engines with SAL modules.
pub struct EngineFactory {
engine: Arc<Engine>,
}
impl EngineFactory {
/// Create a new engine factory with a configured Rhai engine.
pub fn new() -> Self {
let mut engine = Engine::new();
register_sal_modules(&mut engine);
// Logger
hero_logger::rhai_integration::configure_rhai_logging(&mut engine, "system_actor");
Self {
engine: Arc::new(engine),
}
}
/// Get a shared reference to the engine.
pub fn get_engine(&self) -> Arc<Engine> {
Arc::clone(&self.engine)
}
/// Get the global singleton engine factory.
pub fn global() -> &'static EngineFactory {
static FACTORY: OnceLock<EngineFactory> = OnceLock::new();
FACTORY.get_or_init(|| EngineFactory::new())
}
}
pub fn register_sal_modules(engine: &mut Engine) {
let _ = sal_os::rhai::register_os_module(engine);
let _ = sal_redisclient::rhai::register_redisclient_module(engine);
let _ = sal_postgresclient::rhai::register_postgresclient_module(engine);
let _ = sal_process::rhai::register_process_module(engine);
let _ = sal_virt::rhai::register_virt_module(engine);
let _ = sal_git::rhai::register_git_module(engine);
let _ = sal_zinit_client::rhai::register_zinit_module(engine);
let _ = sal_mycelium::rhai::register_mycelium_module(engine);
let _ = sal_text::rhai::register_text_module(engine);
let _ = sal_net::rhai::register_net_module(engine);
let _ = sal_kubernetes::rhai::register_kubernetes_module(engine);
let _ = sal_hetzner::rhai::register_hetzner_module(engine);
println!("SAL modules registered successfully.");
}
/// Create a shared system engine using the factory.
pub fn create_system_engine() -> Arc<Engine> {
EngineFactory::global().get_engine()
}

View File

@@ -1,22 +0,0 @@
/// Engine module for Rhai script execution
///
/// This module provides two different engine configurations:
/// - `system`: SAL modules for system operations (async worker)
/// - `osis`: OSIRIS engine for business operations (sync worker)
pub mod system;
pub mod osis;
pub use osis::create_osis_engine;
pub use system::create_system_engine;
// Re-export common Rhai types for convenience
pub use rhai::{Array, Dynamic, Engine, EvalAltResult, Map};
/// Evaluate a Rhai script string with any engine
pub fn eval_script(
engine: &Engine,
script: &str,
) -> Result<rhai::Dynamic, Box<rhai::EvalAltResult>> {
engine.eval(script)
}

View File

@@ -1,96 +0,0 @@
/// OSIRIS Rhai Engine Integration
///
/// This module provides a Rhai engine configured with OSIRIS object support.
/// It allows Rhai scripts to create Notes, Events, and other OSIRIS objects
/// using a fluent builder pattern and store/retrieve them from HeroDB.
///
/// # Example Rhai Script
///
/// ```rhai
/// // Create a note with builder pattern
/// let note = note("notes")
/// .title("My First Note")
/// .content("This is the content of my note")
/// .tag("topic", "rust")
/// .tag("project", "osiris")
/// .mime("text/plain");
///
/// // Store the note
/// let id = put_note(note);
/// print(`Note stored with ID: ${id}`);
///
/// // Retrieve the note
/// let retrieved = get_note("notes", id);
/// print(`Retrieved: ${retrieved.get_title()}`);
///
/// // Query by tag
/// let ids = query("notes", "tags:tag", "project=osiris");
/// print(`Found ${ids.len()} notes`);
/// ```
use osiris::rhai_support::{register_note_api, register_event_api, OsirisInstance};
use rhai::Engine;
/// Create a new Rhai engine with OSIRIS support
///
/// # Arguments
/// * `herodb_url` - HeroDB connection URL (e.g., "redis://localhost:6379")
/// * `db_id` - Database ID to use
///
/// # Returns
/// A configured Rhai engine with OSIRIS objects and methods registered
pub fn create_osiris_engine(
herodb_url: &str,
db_id: u16,
) -> Result<Engine, Box<dyn std::error::Error>> {
let mut engine = Engine::new();
// Register Note and Event APIs
register_note_api(&mut engine);
register_event_api(&mut engine);
// Register OsirisInstance type
engine.build_type::<OsirisInstance>();
// Register a function to create OSIRIS instances
engine.register_fn("osiris", move |name: &str, url: &str, db_id: rhai::INT| -> Result<OsirisInstance, Box<rhai::EvalAltResult>> {
OsirisInstance::new(name, url, db_id as u16)
.map_err(|e| format!("Failed to create OSIRIS instance: {}", e).into())
});
Ok(engine)
}
/// Example: Run a Rhai script with OSIRIS support
pub fn run_osiris_script(
script: &str,
herodb_url: &str,
db_id: u16,
) -> Result<(), Box<dyn std::error::Error>> {
let engine = create_osiris_engine(herodb_url, db_id)?;
engine.run(script)?;
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_create_engine() {
let engine = create_osiris_engine("redis://localhost:6379", 1);
assert!(engine.is_ok());
}
#[test]
#[ignore] // Requires HeroDB running
fn test_run_script() {
let script = r#"
let note = note("notes");
print(note);
"#;
let result = run_osiris_script(script, "redis://localhost:6379", 1);
assert!(result.is_ok());
}
}

View File

@@ -1,143 +0,0 @@
// use heromodels::models::heroledger::rhai::register_heroledger_rhai_modules;
use rhai::Engine;
use rhailib_dsl;
use std::sync::{Arc, OnceLock};
/// Engine factory for creating and sharing Rhai engines with DSL modules.
pub struct EngineFactory {
engine: Arc<Engine>,
}
impl EngineFactory {
/// Create a new engine factory with a configured Rhai engine.
pub fn new() -> Self {
let mut engine = Engine::new();
register_dsl_modules(&mut engine);
// Logger
hero_logger::rhai_integration::configure_rhai_logging(&mut engine, "osis_actor");
Self {
engine: Arc::new(engine),
}
}
/// Get a shared reference to the engine.
pub fn get_engine(&self) -> Arc<Engine> {
Arc::clone(&self.engine)
}
/// Get the global singleton engine factory.
pub fn global() -> &'static EngineFactory {
static FACTORY: OnceLock<EngineFactory> = OnceLock::new();
FACTORY.get_or_init(|| EngineFactory::new())
}
}
/// Register basic object functions directly in the engine.
/// This provides object functionality without relying on the problematic rhailib_dsl object module.
fn register_object_functions(engine: &mut Engine) {
use heromodels::models::object::Object;
// Register the Object type
engine.register_type_with_name::<Object>("Object");
// Register constructor function
engine.register_fn("new_object", || Object::new());
// Register setter functions
engine.register_fn("object_title", |obj: &mut Object, title: String| {
obj.title = title;
obj.clone()
});
engine.register_fn(
"object_description",
|obj: &mut Object, description: String| {
obj.description = description;
obj.clone()
},
);
// Register getter functions
engine.register_fn("get_object_id", |obj: &mut Object| obj.id() as i64);
engine.register_fn("get_object_title", |obj: &mut Object| obj.title.clone());
engine.register_fn("get_object_description", |obj: &mut Object| {
obj.description.clone()
});
}
/// Registers all DSL modules with the provided Rhai engine.
///
/// This function is the main entry point for integrating the rhailib DSL with a Rhai engine.
/// It registers all business domain modules, making their functions available to Rhai scripts.
///
/// # Arguments
///
/// * `engine` - A mutable reference to the Rhai engine to register modules with
///
/// # Example
///
/// ```rust
/// use rhai::Engine;
/// use runner_rust::engine::osis::register_dsl_modules;
///
/// let mut engine = Engine::new();
/// register_dsl_modules(&mut engine);
///
/// // Engine now has access to all DSL functions
/// let result = engine.eval::<String>(r#"
/// let company = new_company().name("Test Corp");
/// company.name
/// "#).unwrap();
/// assert_eq!(result, "Test Corp");
/// ```
///
/// # Registered Modules
///
/// This function registers the following domain modules:
/// - Access control functions
/// - Business operation functions (companies, products, sales, shareholders)
/// - Calendar and scheduling functions
/// - Circle and community management functions
/// - Company management functions
/// - Contact management functions
/// - Core utility functions
/// - Financial operation functions (accounts, assets, marketplace)
/// - Workflow management functions (flows, steps, signatures)
/// - Library and content management functions
/// - Generic object manipulation functions (custom implementation)
pub fn register_dsl_modules(engine: &mut Engine) {
rhailib_dsl::access::register_access_rhai_module(engine);
rhailib_dsl::biz::register_biz_rhai_module(engine);
rhailib_dsl::calendar::register_calendar_rhai_module(engine);
rhailib_dsl::circle::register_circle_rhai_module(engine);
rhailib_dsl::company::register_company_rhai_module(engine);
rhailib_dsl::contact::register_contact_rhai_module(engine);
rhailib_dsl::core::register_core_rhai_module(engine);
rhailib_dsl::finance::register_finance_rhai_modules(engine);
// rhailib_dsl::flow::register_flow_rhai_modules(engine);
rhailib_dsl::library::register_library_rhai_module(engine);
// Skip problematic object module for now - can be implemented separately if needed
// rhailib_dsl::object::register_object_fns(engine);
rhailib_dsl::payment::register_payment_rhai_module(engine);
// Register basic object functionality directly
register_object_functions(engine);
// heromodels::heroledger::rhai::register_heroledger_rhai_modules(&mut engine);
println!("Rhailib Domain Specific Language modules registered successfully.");
}
/// Create a new osis engine instance.
pub fn create_osis_engine() -> Engine {
let mut engine = Engine::new();
register_dsl_modules(&mut engine);
hero_logger::rhai_integration::configure_rhai_logging(&mut engine, "osis_actor");
engine
}
/// Create a shared osis engine using the factory.
pub fn create_shared_osis_engine() -> Arc<Engine> {
EngineFactory::global().get_engine()
}

View File

@@ -1,124 +0,0 @@
use std::sync::{Arc, OnceLock};
// Re-export common Rhai types for convenience
pub use rhai::{Array, Dynamic, Engine, EvalAltResult, Map};
// Re-export specific functions from sal-os package
pub use sal_os::rhai::{
delete,
// Download functions
download,
download_install,
// File system functions
exist,
file_size,
find_dir,
find_dirs,
find_file,
find_files,
mkdir,
register_os_module,
rsync,
};
// Re-export Redis client module registration function
pub use sal_redisclient::rhai::register_redisclient_module;
// Re-export PostgreSQL client module registration function
pub use sal_postgresclient::rhai::register_postgresclient_module;
pub use sal_process::rhai::{
kill,
process_get,
process_list,
register_process_module,
// Run functions
// Process management functions
which,
};
// Re-export virt functions from sal-virt package
pub use sal_virt::rhai::nerdctl::{
nerdctl_copy,
nerdctl_exec,
nerdctl_image_build,
nerdctl_image_commit,
nerdctl_image_pull,
nerdctl_image_push,
nerdctl_image_remove,
nerdctl_image_tag,
// Image functions
nerdctl_images,
nerdctl_list,
nerdctl_remove,
// Container functions
nerdctl_run,
nerdctl_run_with_name,
nerdctl_run_with_port,
nerdctl_stop,
};
pub use sal_virt::rhai::{
bah_new, register_bah_module, register_nerdctl_module, register_rfs_module,
};
pub use sal_git::rhai::register_git_module;
pub use sal_git::{GitRepo, GitTree};
pub use sal_zinit_client::rhai::register_zinit_module;
pub use sal_mycelium::rhai::register_mycelium_module;
pub use sal_text::rhai::register_text_module;
pub use sal_net::rhai::register_net_module;
pub use sal_kubernetes::rhai::register_kubernetes_module;
pub use sal_kubernetes::KubernetesManager;
pub use sal_os::rhai::copy as os_copy;
pub use sal_hetzner::rhai::register_hetzner_module;
/// Engine factory for creating and sharing Rhai engines with SAL modules.
pub struct EngineFactory {
engine: Arc<Engine>,
}
impl EngineFactory {
/// Create a new engine factory with a configured Rhai engine.
pub fn new() -> Self {
let mut engine = Engine::new();
register_sal_modules(&mut engine);
// Logger
hero_logger::rhai_integration::configure_rhai_logging(&mut engine, "system_actor");
Self {
engine: Arc::new(engine),
}
}
/// Get a shared reference to the engine.
pub fn get_engine(&self) -> Arc<Engine> {
Arc::clone(&self.engine)
}
/// Get the global singleton engine factory.
pub fn global() -> &'static EngineFactory {
static FACTORY: OnceLock<EngineFactory> = OnceLock::new();
FACTORY.get_or_init(|| EngineFactory::new())
}
}
pub fn register_sal_modules(engine: &mut Engine) {
let _ = sal_os::rhai::register_os_module(engine);
let _ = sal_redisclient::rhai::register_redisclient_module(engine);
let _ = sal_postgresclient::rhai::register_postgresclient_module(engine);
let _ = sal_process::rhai::register_process_module(engine);
let _ = sal_virt::rhai::register_virt_module(engine);
let _ = sal_git::rhai::register_git_module(engine);
let _ = sal_zinit_client::rhai::register_zinit_module(engine);
let _ = sal_mycelium::rhai::register_mycelium_module(engine);
let _ = sal_text::rhai::register_text_module(engine);
let _ = sal_net::rhai::register_net_module(engine);
let _ = sal_kubernetes::rhai::register_kubernetes_module(engine);
let _ = sal_hetzner::rhai::register_hetzner_module(engine);
println!("SAL modules registered successfully.");
}
/// Create a shared system engine using the factory.
pub fn create_system_engine() -> Arc<Engine> {
EngineFactory::global().get_engine()
}

View File

@@ -1,5 +1,4 @@
// Core modules
pub mod engine;
pub mod async_runner;
pub mod sync_runner;
pub mod runner_trait;
@@ -11,8 +10,6 @@ pub mod client;
pub use runner_trait::{Runner, RunnerConfig, spawn_runner};
pub use async_runner::{AsyncRunner, spawn_async_runner};
pub use sync_runner::{SyncRunner, SyncRunnerConfig, spawn_sync_runner};
pub use engine::system::{register_sal_modules, create_system_engine};
pub use engine::osis::{register_dsl_modules, create_osis_engine, create_shared_osis_engine};
// Re-export job types from local job module
pub use job::{Job, JobStatus, JobError, JobBuilder};

View File

@@ -3,6 +3,7 @@ use crate::runner_trait::Runner;
use log::{debug, error, info};
use rhai::{Engine, Dynamic};
use std::sync::Arc;
use tracing::subscriber::with_default;
/// Configuration for sync runner instances
#[derive(Debug, Clone)]
@@ -72,11 +73,58 @@ impl Runner for SyncRunner {
debug!("Sync Runner '{}', Job {}: Processing started.", runner_id, job_id);
info!("Sync Runner '{}' processing job_id: {}. Script: {:.50}...", job.context_id, job_id, job.payload);
// Create a new engine instance (cheap with factory pattern)
let mut engine = (self.engine_factory)();
// Determine logs directory (default to ~/hero/logs)
let logs_root = if let Some(home) = std::env::var_os("HOME") {
std::path::PathBuf::from(home).join("hero").join("logs")
} else {
std::path::PathBuf::from("logs")
};
// Execute the script
match Self::execute_job_with_engine(&mut engine, &job) {
// Create job-specific logger
let job_logger_result = hero_logger::create_job_logger_with_guard(
&logs_root,
runner_id, // Use runner_id as the actor_type
job_id,
);
// Verify signatures before executing (if any)
if let Err(e) = job.verify_signatures() {
error!("Job {} signature verification failed: {}", job_id, e);
return Err(Box::new(e));
}
// Execute job within logging context
let result = match job_logger_result {
Ok((job_logger, _guard)) => {
// Execute ALL job processing within logging context
with_default(job_logger, || {
tracing::info!("Job {} started", job_id);
// Create a new engine instance and configure Rhai logging
let mut engine = (self.engine_factory)();
// Reconfigure Rhai logging for this specific job context
// This ensures print() and debug() calls go to the job logger
hero_logger::rhai_integration::configure_rhai_logging(&mut engine, runner_id);
// Execute the script
let script_result = Self::execute_job_with_engine(&mut engine, &job);
tracing::info!("Job {} completed", job_id);
script_result
})
}
Err(e) => {
error!("Failed to create job logger for job {}: {}", job_id, e);
// Fallback: execute without job-specific logging
let mut engine = (self.engine_factory)();
Self::execute_job_with_engine(&mut engine, &job)
}
};
// Process result
match result {
Ok(result) => {
let output_str = if result.is::<String>() {
result.into_string().unwrap()