1use super::Command;
2use crate::context::AppContext;
3use crate::server::TskServer;
4use crate::task::{Task, TaskStatus};
5use crate::task_manager::TaskManager;
6use crate::task_storage::get_task_storage;
7use async_trait::async_trait;
8use std::error::Error;
9use std::sync::Arc;
10
11pub struct RunCommand {
12 pub server: bool,
13}
14
15#[async_trait]
16impl Command for RunCommand {
17 async fn execute(&self, ctx: &AppContext) -> Result<(), Box<dyn Error>> {
18 if self.server {
19 println!("Starting TSK server...");
21 let server = TskServer::new(Arc::new(ctx.clone()));
22
23 let shutdown_signal = Arc::new(tokio::sync::Notify::new());
25 let shutdown_signal_clone = shutdown_signal.clone();
26
27 tokio::spawn(async move {
28 tokio::signal::ctrl_c()
29 .await
30 .expect("Failed to listen for Ctrl+C");
31 println!("\nReceived shutdown signal...");
32 shutdown_signal_clone.notify_one();
33 });
34
35 tokio::select! {
37 result = server.run() => {
38 match result {
39 Ok(_) => {},
40 Err(e) => {
41 let error_msg = e.to_string();
42 eprintln!("Server error: {error_msg}");
43 return Err(Box::new(std::io::Error::other(error_msg)));
44 }
45 }
46 }
47 _ = shutdown_signal.notified() => {
48 server.shutdown().await;
49 }
50 }
51
52 println!("Server stopped");
53 return Ok(());
54 }
55
56 let storage = get_task_storage(ctx.xdg_directories(), ctx.file_system());
58 let tasks = storage
59 .list_tasks()
60 .await
61 .map_err(|e| e as Box<dyn Error>)?;
62
63 let queued_tasks: Vec<Task> = tasks
64 .into_iter()
65 .filter(|t| t.status == TaskStatus::Queued)
66 .collect();
67
68 if queued_tasks.is_empty() {
69 println!("No queued tasks to run");
70 return Ok(());
71 }
72
73 println!("Found {} queued task(s) to run", queued_tasks.len());
74
75 let task_manager = TaskManager::with_storage(ctx)?;
76 let total_tasks = queued_tasks.len();
77 let mut succeeded = 0;
78 let mut failed = 0;
79
80 for task in queued_tasks {
81 println!("\n{}", "=".repeat(60));
82 println!("Running task: {} ({})", task.name, task.id);
83 println!("Type: {}", task.task_type);
84 println!("{}", "=".repeat(60));
85
86 ctx.terminal_operations()
88 .set_title(&format!("TSK: {}", task.name));
89
90 match task_manager.execute_queued_task(&task).await {
92 Ok(_result) => {
93 println!("\nTask completed successfully");
94 succeeded += 1;
95 }
96 Err(e) => {
97 eprintln!("Task failed: {}", e.message);
98 failed += 1;
99 }
100 }
101 }
102
103 ctx.terminal_operations().restore_title();
105
106 println!("\n{}", "=".repeat(60));
107 println!("All tasks processed!");
108 println!("Use 'tsk list' to see the final status of all tasks");
109
110 ctx.notification_client()
112 .notify_all_tasks_complete(total_tasks, succeeded, failed);
113
114 Ok(())
115 }
116}