Skip to main content

nsg_cli/commands/
status.rs

1use crate::client::NsgClient;
2use crate::config::Credentials;
3use anyhow::Result;
4use clap::Args;
5use colored::Colorize;
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!(
63                    "  [{}] {}",
64                    msg.stage.cyan(),
65                    msg.timestamp.as_deref().unwrap_or("")
66                );
67                if !msg.text.is_empty() {
68                    let text = if msg.text.len() > 200 {
69                        format!("{}...", &msg.text[..200])
70                    } else {
71                        msg.text.clone()
72                    };
73                    println!("    {}", text);
74                }
75            }
76        }
77
78        println!();
79        println!("{}", "=".repeat(80));
80        println!();
81
82        print_next_action(&status.job_stage, &self.job);
83
84        Ok(())
85    }
86}
87
88fn get_stage_icon(stage: &str) -> &'static str {
89    match stage {
90        "COMPLETED" => "✓",
91        "RUNNING" | "RUN" => "⟳",
92        "QUEUE" | "SUBMITTED" => "⏳",
93        "FAILED" => "✗",
94        _ => "?",
95    }
96}
97
98fn format_timestamp(ts: &str) -> String {
99    use chrono::{DateTime, Utc};
100    if let Ok(dt) = ts.parse::<DateTime<Utc>>() {
101        dt.format("%Y-%m-%d %H:%M:%S UTC").to_string()
102    } else {
103        ts.to_string()
104    }
105}
106
107fn print_next_action(stage: &str, job_id: &str) {
108    match stage {
109        "COMPLETED" => {
110            println!(
111                "{} Job completed! You can now download results.",
112                "✓".green().bold()
113            );
114            println!();
115            println!("To download all results:");
116            println!("  {}", format!("nsg download {}", job_id).cyan());
117        }
118        "FAILED" => {
119            println!(
120                "{} Job failed. Check messages above for error details.",
121                "✗".red().bold()
122            );
123        }
124        "QUEUE" | "SUBMITTED" => {
125            println!("{} Job is queued. Check again later.", "⏳".yellow());
126            println!();
127            println!("To check status again:");
128            println!("  {}", format!("nsg status {}", job_id).cyan());
129        }
130        "RUN" | "RUNNING" => {
131            println!(
132                "{} Job is running. Check back later for completion.",
133                "⟳".yellow()
134            );
135            println!();
136            println!("To check status again:");
137            println!("  {}", format!("nsg status {}", job_id).cyan());
138        }
139        _ => {
140            println!("{} Unknown job stage: {}", "?".yellow(), stage);
141        }
142    }
143    println!();
144}