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