cargo-hammerwork 1.0.0

A comprehensive cargo subcommand for managing Hammerwork job queues with advanced tooling and monitoring capabilities
Documentation
use comfy_table::Table;
use std::fmt;

pub struct JobTable {
    table: Table,
}

impl Default for JobTable {
    fn default() -> Self {
        Self::new()
    }
}

impl JobTable {
    pub fn new() -> Self {
        let mut table = Table::new();
        table.set_header(vec![
            "ID",
            "Queue",
            "Status",
            "Priority",
            "Attempts",
            "Created At",
            "Scheduled At",
        ]);
        Self { table }
    }
    
    #[allow(clippy::too_many_arguments)]
    pub fn add_job_row(
        &mut self,
        id: &str,
        queue_name: &str,
        status: &str,
        priority: &str,
        attempts: i32,
        created_at: &str,
        scheduled_at: &str,
    ) {
        let status_colored = match status {
            "pending" => format!("🟡 {}", status),
            "running" => format!("🔵 {}", status),
            "completed" => format!("🟢 {}", status),
            "failed" => format!("🔴 {}", status),
            "dead" => format!("💀 {}", status),
            "retrying" => format!("🟠 {}", status),
            _ => status.to_string(),
        };
        
        let priority_colored = match priority {
            "critical" => format!("🚨 {}", priority),
            "high" => format!("{}", priority),
            "normal" => format!("📝 {}", priority),
            "low" => format!("🐌 {}", priority),
            "background" => format!("💤 {}", priority),
            _ => priority.to_string(),
        };
        
        self.table.add_row(vec![
            &id[..8.min(id.len())],
            queue_name,
            &status_colored,
            &priority_colored,
            &attempts.to_string(),
            created_at,
            scheduled_at,
        ]);
    }
}

impl fmt::Display for JobTable {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}", self.table)
    }
}

pub struct StatsTable {
    table: Table,
}

impl Default for StatsTable {
    fn default() -> Self {
        Self::new()
    }
}

impl StatsTable {
    pub fn new() -> Self {
        let mut table = Table::new();
        table.set_header(vec!["Status", "Priority", "Count"]);
        Self { table }
    }
    
    pub fn add_stats_row(&mut self, status: &str, priority: &str, count: i64) {
        let status_icon = match status {
            "pending" => "🟡",
            "running" => "🔵",
            "completed" => "🟢",
            "failed" => "🔴",
            "dead" => "💀",
            "retrying" => "🟠",
            _ => "",
        };
        
        let priority_icon = match priority {
            "critical" => "🚨",
            "high" => "",
            "normal" => "📝",
            "low" => "🐌",
            "background" => "💤",
            _ => "",
        };
        
        self.table.add_row(vec![
            &format!("{} {}", status_icon, status),
            &format!("{} {}", priority_icon, priority),
            &count.to_string(),
        ]);
    }
}

impl fmt::Display for StatsTable {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}", self.table)
    }
}

pub fn format_duration(seconds: Option<i64>) -> String {
    match seconds {
        Some(secs) if secs < 60 => format!("{}s", secs),
        Some(secs) if secs < 3600 => format!("{}m {}s", secs / 60, secs % 60),
        Some(secs) => format!("{}h {}m", secs / 3600, (secs % 3600) / 60),
        None => "N/A".to_string(),
    }
}

pub fn format_size(bytes: Option<i64>) -> String {
    match bytes {
        Some(b) if b < 1024 => format!("{}B", b),
        Some(b) if b < 1024 * 1024 => format!("{:.1}KB", b as f64 / 1024.0),
        Some(b) if b < 1024 * 1024 * 1024 => format!("{:.1}MB", b as f64 / (1024.0 * 1024.0)),
        Some(b) => format!("{:.1}GB", b as f64 / (1024.0 * 1024.0 * 1024.0)),
        None => "N/A".to_string(),
    }
}