merge runners into single project
This commit is contained in:
153
cmd/sync_actor_tui.rs
Normal file
153
cmd/sync_actor_tui.rs
Normal file
@@ -0,0 +1,153 @@
|
||||
//! Terminal UI for Sync Actor - Monitor and dispatch jobs to sync actor with DSL modules
|
||||
//!
|
||||
//! This binary provides a TUI interface for monitoring and dispatching jobs to the sync actor.
|
||||
|
||||
use anyhow::{Result, Context};
|
||||
use clap::Parser;
|
||||
use log::{info, warn, error};
|
||||
use std::path::PathBuf;
|
||||
use std::process::{Child, Command};
|
||||
use tokio::signal;
|
||||
|
||||
#[derive(Parser)]
|
||||
#[command(name = "sync-actor-tui")]
|
||||
#[command(about = "Terminal UI for Sync Actor - Monitor and dispatch jobs with DSL modules")]
|
||||
struct Args {
|
||||
/// Actor ID for this instance
|
||||
#[arg(short, long, default_value = "sync_osis")]
|
||||
actor_id: String,
|
||||
|
||||
/// Redis URL for job queue
|
||||
#[arg(short, long, default_value = "redis://localhost:6379")]
|
||||
redis_url: String,
|
||||
|
||||
/// Database path
|
||||
#[arg(short, long, default_value = "/tmp/actor_db")]
|
||||
db_path: String,
|
||||
|
||||
/// Preserve completed tasks in Redis (don't delete them)
|
||||
#[arg(short, long, default_value = "false")]
|
||||
preserve_tasks: bool,
|
||||
|
||||
/// Enable verbose logging
|
||||
#[arg(short, long)]
|
||||
verbose: bool,
|
||||
}
|
||||
|
||||
/// Initialize logging based on verbosity level
|
||||
fn init_logging(verbose: bool) {
|
||||
if verbose {
|
||||
env_logger::Builder::from_default_env()
|
||||
.filter_level(log::LevelFilter::Debug)
|
||||
.init();
|
||||
} else {
|
||||
env_logger::Builder::from_default_env()
|
||||
.filter_level(log::LevelFilter::Info)
|
||||
.init();
|
||||
}
|
||||
}
|
||||
|
||||
/// Spawn the sync actor binary as a background process
|
||||
fn spawn_actor_process(args: &Args) -> Result<Child> {
|
||||
// Get the crate root directory
|
||||
let crate_root = std::env::var("CARGO_MANIFEST_DIR")
|
||||
.unwrap_or_else(|_| ".".to_string());
|
||||
let actor_path = PathBuf::from(crate_root).join("target/debug/sync_actor");
|
||||
info!("🎬 Spawning sync actor process: {}", actor_path.display());
|
||||
|
||||
let mut cmd = Command::new(&actor_path);
|
||||
|
||||
// Add command line arguments
|
||||
cmd.args(&[
|
||||
"--actor-id", &args.actor_id,
|
||||
"--db-path", &args.db_path,
|
||||
"--redis-url", &args.redis_url,
|
||||
"--preserve-tasks", &args.preserve_tasks.to_string(),
|
||||
]);
|
||||
|
||||
// Redirect stdout and stderr to null to prevent logs from interfering with TUI
|
||||
cmd.stdout(std::process::Stdio::null())
|
||||
.stderr(std::process::Stdio::null());
|
||||
|
||||
// Spawn the process
|
||||
let child = cmd
|
||||
.spawn()
|
||||
.with_context(|| format!("Failed to spawn sync actor process: {}", actor_path.display()))?;
|
||||
|
||||
info!("✅ Sync actor process spawned with PID: {}", child.id());
|
||||
Ok(child)
|
||||
}
|
||||
|
||||
/// Cleanup function to terminate actor process
|
||||
fn cleanup_actor_process(mut actor_process: Child) {
|
||||
info!("🧹 Cleaning up sync actor process...");
|
||||
|
||||
match actor_process.try_wait() {
|
||||
Ok(Some(status)) => {
|
||||
info!("Sync actor process already exited with status: {}", status);
|
||||
}
|
||||
Ok(None) => {
|
||||
info!("Terminating sync actor process...");
|
||||
if let Err(e) = actor_process.kill() {
|
||||
error!("Failed to kill sync actor process: {}", e);
|
||||
} else {
|
||||
match actor_process.wait() {
|
||||
Ok(status) => info!("Sync actor process terminated with status: {}", status),
|
||||
Err(e) => error!("Failed to wait for sync actor process: {}", e),
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
error!("Failed to check sync actor process status: {}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<()> {
|
||||
let args = Args::parse();
|
||||
|
||||
// Initialize logging
|
||||
init_logging(args.verbose);
|
||||
|
||||
let crate_root = std::env::var("CARGO_MANIFEST_DIR")
|
||||
.unwrap_or_else(|_| ".".to_string());
|
||||
|
||||
info!("🚀 Starting Sync Actor TUI...");
|
||||
info!("Actor ID: {}", args.actor_id);
|
||||
info!("Actor Path: {}/target/debug/sync_actor", crate_root);
|
||||
info!("Redis URL: {}", args.redis_url);
|
||||
info!("Database Path: {}", args.db_path);
|
||||
info!("Preserve Tasks: {}", args.preserve_tasks);
|
||||
info!("Script Type: DSL (Domain Specific Language)");
|
||||
|
||||
// Spawn the actor process first
|
||||
let actor_process = spawn_actor_process(&args)?;
|
||||
|
||||
// Give the actor a moment to start up
|
||||
tokio::time::sleep(tokio::time::Duration::from_millis(500)).await;
|
||||
|
||||
info!("📋 Sync Actor TUI is running. The actor processes jobs sequentially.");
|
||||
info!("💡 Use Redis CLI or job submission tools to send jobs to queue: actor_queue:{}", args.actor_id);
|
||||
info!("🔄 Jobs will be processed with DSL modules (business operations)");
|
||||
info!("📊 Jobs are processed one at a time in order");
|
||||
if args.preserve_tasks {
|
||||
info!("💾 Completed tasks will be preserved in Redis");
|
||||
} else {
|
||||
info!("🗑️ Completed tasks will be cleaned up from Redis");
|
||||
}
|
||||
info!("Press Ctrl+C to exit...");
|
||||
|
||||
// Wait for Ctrl+C
|
||||
let result = tokio::select! {
|
||||
_ = signal::ctrl_c() => {
|
||||
info!("Received Ctrl+C, shutting down...");
|
||||
Ok(())
|
||||
}
|
||||
};
|
||||
|
||||
// Clean up the actor process
|
||||
cleanup_actor_process(actor_process);
|
||||
|
||||
result
|
||||
}
|
Reference in New Issue
Block a user