first commit
This commit is contained in:
73
src/bin/runner/engine.rs
Normal file
73
src/bin/runner/engine.rs
Normal file
@@ -0,0 +1,73 @@
|
||||
/// OSIRIS Engine Factory
|
||||
///
|
||||
/// Creates a Rhai engine configured with OSIRIS objects and methods.
|
||||
|
||||
use osiris::rhai_support::{register_note_api, register_event_api, OsirisInstance};
|
||||
use rhai::Engine;
|
||||
use std::collections::HashMap;
|
||||
|
||||
#[allow(dead_code)]
|
||||
|
||||
/// Configuration for multiple OSIRIS instances
|
||||
pub struct OsirisConfig {
|
||||
pub instances: HashMap<String, (String, u16)>, // name -> (url, db_id)
|
||||
}
|
||||
|
||||
impl OsirisConfig {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
instances: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_instance(&mut self, name: impl ToString, url: impl ToString, db_id: u16) {
|
||||
self.instances.insert(name.to_string(), (url.to_string(), db_id));
|
||||
}
|
||||
|
||||
pub fn single(url: impl ToString, db_id: u16) -> Self {
|
||||
let mut config = Self::new();
|
||||
config.add_instance("default", url, db_id);
|
||||
config
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a new Rhai engine with OSIRIS support
|
||||
pub fn create_osiris_engine(
|
||||
herodb_url: &str,
|
||||
db_id: u16,
|
||||
) -> Result<(Engine, rhai::Scope<'static>), Box<dyn std::error::Error>> {
|
||||
let config = OsirisConfig::single(herodb_url, db_id);
|
||||
create_osiris_engine_with_config(config)
|
||||
}
|
||||
|
||||
/// Create a new Rhai engine with multiple OSIRIS instances
|
||||
/// Returns (Engine, Scope) where Scope contains predefined instances
|
||||
pub fn create_osiris_engine_with_config(
|
||||
config: OsirisConfig,
|
||||
) -> Result<(Engine, rhai::Scope<'static>), Box<dyn std::error::Error>> {
|
||||
let mut engine = Engine::new();
|
||||
|
||||
// Register Note API
|
||||
register_note_api(&mut engine);
|
||||
|
||||
// Register Event API
|
||||
register_event_api(&mut engine);
|
||||
|
||||
// Register OsirisInstance type
|
||||
engine.build_type::<OsirisInstance>();
|
||||
|
||||
// Register osiris() constructor function for dynamic creation
|
||||
engine.register_fn("osiris", |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())
|
||||
});
|
||||
|
||||
// Create predefined instances and inject them as global constants in scope
|
||||
let mut scope = rhai::Scope::new();
|
||||
for (name, (url, db_id)) in config.instances {
|
||||
let instance = OsirisInstance::new(&name, &url, db_id)?;
|
||||
scope.push_constant(&name, instance);
|
||||
}
|
||||
|
||||
Ok((engine, scope))
|
||||
}
|
||||
135
src/bin/runner/main.rs
Normal file
135
src/bin/runner/main.rs
Normal file
@@ -0,0 +1,135 @@
|
||||
/// OSIRIS Runner
|
||||
///
|
||||
/// A standalone runner for executing OSIRIS Rhai scripts.
|
||||
/// Can run in script mode (single execution) or daemon mode (continuous).
|
||||
///
|
||||
/// Usage:
|
||||
/// ```bash
|
||||
/// # Script mode
|
||||
/// cargo run --bin runner --features rhai-support -- runner1 --script "let note = note('test').title('Hi'); put_note(note);"
|
||||
///
|
||||
/// # Daemon mode (requires runner_rust infrastructure)
|
||||
/// cargo run --bin runner --features rhai-support -- runner1 --redis-url redis://localhost:6379
|
||||
/// ```
|
||||
|
||||
use clap::Parser;
|
||||
|
||||
#[cfg(feature = "rhai-support")]
|
||||
mod engine;
|
||||
|
||||
#[cfg(feature = "rhai-support")]
|
||||
use engine::create_osiris_engine;
|
||||
|
||||
#[derive(Parser, Debug)]
|
||||
#[command(author, version, about = "OSIRIS Rhai Script Runner", long_about = None)]
|
||||
struct Args {
|
||||
/// Runner ID
|
||||
runner_id: String,
|
||||
|
||||
/// HeroDB URL
|
||||
#[arg(short = 'r', long, default_value = "redis://localhost:6379")]
|
||||
redis_url: String,
|
||||
|
||||
/// HeroDB database ID
|
||||
#[arg(short = 'd', long, default_value_t = 1)]
|
||||
db_id: u16,
|
||||
|
||||
/// Script to execute in single-job mode (optional)
|
||||
#[arg(short, long)]
|
||||
script: Option<String>,
|
||||
|
||||
/// Script file to execute
|
||||
#[arg(short = 'f', long)]
|
||||
script_file: Option<String>,
|
||||
|
||||
/// Predefined instances in format: name:url:db_id (can be repeated)
|
||||
/// Example: --instance freezone:redis://localhost:6379:1
|
||||
#[arg(short = 'i', long = "instance")]
|
||||
instances: Vec<String>,
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "rhai-support"))]
|
||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
eprintln!("❌ Error: OSIRIS runner requires the 'rhai-support' feature");
|
||||
eprintln!("Run with: cargo run --bin runner --features rhai-support");
|
||||
std::process::exit(1);
|
||||
}
|
||||
|
||||
#[cfg(feature = "rhai-support")]
|
||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
// Initialize logging
|
||||
env_logger::init();
|
||||
|
||||
let args = Args::parse();
|
||||
|
||||
println!("🚀 OSIRIS Runner");
|
||||
println!("Runner ID: {}", args.runner_id);
|
||||
println!("HeroDB: {} (DB {})", args.redis_url, args.db_id);
|
||||
|
||||
// Parse predefined instances
|
||||
let mut config = engine::OsirisConfig::new();
|
||||
|
||||
if args.instances.is_empty() {
|
||||
// No predefined instances, use default
|
||||
config.add_instance("default", &args.redis_url, args.db_id);
|
||||
} else {
|
||||
// Parse instance definitions (format: name:url:db_id)
|
||||
// We need to split carefully since URL contains colons
|
||||
for instance_def in &args.instances {
|
||||
// Find the first colon (name separator)
|
||||
let first_colon = instance_def.find(':')
|
||||
.ok_or_else(|| format!("Invalid instance format: '{}'. Expected: name:url:db_id", instance_def))?;
|
||||
|
||||
let name = &instance_def[..first_colon];
|
||||
let rest = &instance_def[first_colon + 1..];
|
||||
|
||||
// Find the last colon (db_id separator)
|
||||
let last_colon = rest.rfind(':')
|
||||
.ok_or_else(|| format!("Invalid instance format: '{}'. Expected: name:url:db_id", instance_def))?;
|
||||
|
||||
let url = &rest[..last_colon];
|
||||
let db_id_str = &rest[last_colon + 1..];
|
||||
|
||||
let db_id: u16 = db_id_str.parse()
|
||||
.map_err(|_| format!("Invalid db_id in instance '{}': {}", instance_def, db_id_str))?;
|
||||
|
||||
config.add_instance(name, url, db_id);
|
||||
println!(" Instance: {} → {} (DB {})", name, url, db_id);
|
||||
}
|
||||
}
|
||||
|
||||
println!();
|
||||
|
||||
// Determine script source
|
||||
let script_content = if let Some(script) = args.script {
|
||||
script
|
||||
} else if let Some(file_path) = args.script_file {
|
||||
std::fs::read_to_string(&file_path)
|
||||
.map_err(|e| format!("Failed to read script file '{}': {}", file_path, e))?
|
||||
} else {
|
||||
return Err("No script provided. Use --script or --script-file".into());
|
||||
};
|
||||
|
||||
println!("📝 Executing script...\n");
|
||||
println!("─────────────────────────────────────");
|
||||
|
||||
// Create engine with predefined instances
|
||||
let (engine, mut scope) = engine::create_osiris_engine_with_config(config)?;
|
||||
|
||||
match engine.eval_with_scope::<rhai::Dynamic>(&mut scope, &script_content) {
|
||||
Ok(result) => {
|
||||
println!("─────────────────────────────────────");
|
||||
println!("\n✅ Script completed successfully!");
|
||||
if !result.is_unit() {
|
||||
println!("Result: {}", result);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
Err(e) => {
|
||||
println!("─────────────────────────────────────");
|
||||
println!("\n❌ Script execution failed!");
|
||||
println!("Error: {}", e);
|
||||
Err(Box::new(e))
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user