nsg_cli/commands/
status.rs

1use anyhow::Result;
2use clap::Args;
3use colored::Colorize;
4use crate::client::NsgClient;
5use crate::config::Credentials;
6
7#[derive(Debug, Args)]
8pub struct StatusCommand {
9    #[arg(help = "Job URL or Job ID")]
10    job: String,
11}
12
13impl StatusCommand {
14    pub fn execute(self) -> Result<()> {
15        let credentials = Credentials::load()?;
16        let client = NsgClient::new(credentials)?;
17
18        println!("{}", "NSG Job Status".bold().cyan());
19        println!("{}", "=".repeat(80).cyan());
20        println!();
21        println!("{} Checking job status...", "→".cyan());
22        println!("   Job: {}", self.job.bold());
23        println!();
24
25        let status = client.get_job_status(&self.job)?;
26
27        println!("{} Job found", "✓".green().bold());
28        println!();
29        println!("{}", "Job Status Information".bold());
30        println!("{}", "=".repeat(80));
31        println!();
32        println!("Job ID:       {}", status.job_id.cyan());
33
34        let stage_icon = get_stage_icon(&status.job_stage);
35        println!("Stage:        {} {}", stage_icon, status.job_stage.bold());
36
37        if status.failed {
38            println!("Failed:       {} YES", "✗".red().bold());
39        }
40
41        if let Some(date) = &status.date_submitted {
42            println!("Submitted:    {}", format_timestamp(date));
43        }
44
45        if status.results_uri.is_some() {
46            println!("Results:      {} Available", "✓".green());
47        } else {
48            println!("Results:      {} Not yet available", "⏳".yellow());
49        }
50
51        if !status.messages.is_empty() {
52            println!();
53            println!("{}", "Recent Messages:".bold());
54            let recent = if status.messages.len() > 5 {
55                &status.messages[status.messages.len() - 5..]
56            } else {
57                &status.messages[..]
58            };
59
60            for msg in recent {
61                println!();
62                println!("  [{}] {}", msg.stage.cyan(), msg.timestamp.as_deref().unwrap_or(""));
63                if !msg.text.is_empty() {
64                    let text = if msg.text.len() > 200 {
65                        format!("{}...", &msg.text[..200])
66                    } else {
67                        msg.text.clone()
68                    };
69                    println!("    {}", text);
70                }
71            }
72        }
73
74        println!();
75        println!("{}", "=".repeat(80));
76        println!();
77
78        print_next_action(&status.job_stage, &self.job);
79
80        Ok(())
81    }
82}
83
84fn get_stage_icon(stage: &str) -> &'static str {
85    match stage {
86        "COMPLETED" => "✓",
87        "RUNNING" | "RUN" => "⟳",
88        "QUEUE" | "SUBMITTED" => "⏳",
89        "FAILED" => "✗",
90        _ => "?",
91    }
92}
93
94fn format_timestamp(ts: &str) -> String {
95    use chrono::{DateTime, Utc};
96    if let Ok(dt) = ts.parse::<DateTime<Utc>>() {
97        dt.format("%Y-%m-%d %H:%M:%S UTC").to_string()
98    } else {
99        ts.to_string()
100    }
101}
102
103fn print_next_action(stage: &str, job_id: &str) {
104    match stage {
105        "COMPLETED" => {
106            println!("{} Job completed! You can now download results.", "✓".green().bold());
107            println!();
108            println!("To download all results:");
109            println!("  {}", format!("nsg download {}", job_id).cyan());
110        }
111        "FAILED" => {
112            println!("{} Job failed. Check messages above for error details.", "✗".red().bold());
113        }
114        "QUEUE" | "SUBMITTED" => {
115            println!("{} Job is queued. Check again later.", "⏳".yellow());
116            println!();
117            println!("To check status again:");
118            println!("  {}", format!("nsg status {}", job_id).cyan());
119        }
120        "RUN" | "RUNNING" => {
121            println!("{} Job is running. Check back later for completion.", "⟳".yellow());
122            println!();
123            println!("To check status again:");
124            println!("  {}", format!("nsg status {}", job_id).cyan());
125        }
126        _ => {
127            println!("{} Unknown job stage: {}", "?".yellow(), stage);
128        }
129    }
130    println!();
131}