1use std::fmt;
2use std::fmt::{Display, Formatter};
3
4use colored::Colorize;
5
6use crate::{limit_string, MainProgress, Uid, WorkerTemplate};
7
8pub struct WorkerState<S> {
9 pub(super) id: Uid,
10 pub(super) status: WorkerStatus,
11 pub(super) jobs_count: usize,
12 pub(super) task: String,
13 pub(super) main_progress: MainProgress<S>,
14 pub(super) channel_active: usize,
15}
16
17impl<S> WorkerState<S>
18where
19 S: WorkerTemplate,
20{
21 pub fn new(id: Uid, main_progress: MainProgress<S>) -> Self {
22 Self {
23 id,
24 status: WorkerStatus::Spawned,
25 jobs_count: 0,
26 task: "Idling..".to_string(),
27 main_progress,
28 channel_active: 0,
29 }
30 }
31
32 pub fn update(
33 &mut self,
34 ch: impl Into<Option<usize>>,
35 task: impl Into<Option<String>>,
36 jobs: impl Into<Option<usize>>,
37 status: impl Into<Option<WorkerStatus>>,
38 ) {
39 let (ch, task, jobs, status) = (ch.into(), task.into(), jobs.into(), status.into());
40 if ch.is_none() && task.is_none() && jobs.is_none() && status.is_none() {
41 return;
42 }
43
44 if let Some(ch) = ch {
45 self.channel_active = ch;
46 }
47 if let Some(task) = task {
48 self.task = limit_string(43, task, None);
49 }
50 if let Some(jobs) = jobs {
51 self.jobs_count = jobs;
52 }
53 if let Some(status) = status {
54 self.status = status;
55 }
56
57 self.main_progress.edit_worker(self.id, self.to_string());
58 }
59
60 fn id(&self) -> impl Display {
61 limit_string(4, self.id, None)
62 }
63
64 pub fn channel_active(&self) -> impl Display {
65 format!("{}: {}", "Channel".bright_magenta(), self.channel_active)
66 }
67
68 fn status(&self) -> impl Display {
69 format!("{}: {}", "Status".bright_yellow(), self.status)
70 }
71
72 fn jobs(&self) -> impl Display {
73 format!("{}: {}", "Jobs Count".bright_yellow(), self.jobs_count)
74 }
75 fn task(&self) -> impl Display {
76 format!("{}: {}", "Task".bright_yellow(), self.task.bright_yellow())
77 }
78
79 pub fn set_channel(&mut self, count: usize) {
80 self.channel_active = count;
81 self.main_progress.edit_worker(self.id, self.to_string());
82 }
83
84 pub fn set_status(&mut self, status: WorkerStatus) {
85 self.status = status;
86 self.main_progress.edit_worker(self.id, format!("{self}"));
87 }
88 pub fn set_jobs(&mut self, count: usize) {
89 self.jobs_count = count;
90 self.main_progress.edit_worker(self.id, format!("{self}"));
91 }
92 pub fn set_task(&mut self, task: impl ToString) {
93 self.task = limit_string(43, task, None);
94 self.main_progress.edit_worker(self.id, format!("{self}"));
95 }
96}
97
98#[derive(Clone)]
99pub enum WorkerStatus {
100 Running,
101 Stopped,
102 Waiting,
103 Spawned,
104}
105
106impl Display for WorkerStatus {
107 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
108 use WorkerStatus::*;
109 match *self {
110 Running => write!(f, " {{spinner}} {}", "RUNNING".bright_green()),
111 Stopped => write!(f, "🛑 {}", "STOPPED".bright_red()),
112 Waiting => write!(f, "⌛ {}", "WAITING".bright_magenta()),
113 Spawned => write!(f, "⬆️ {}", "SPAWNED".bright_white()),
114 }
115 }
116}
117
118impl<S> Display for WorkerState<S>
119where
120 S: WorkerTemplate,
121{
122 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
123 write!(
124 f,
125 "[ Worker #{} ] {} │ {} │ {} │ {}",
126 self.id(),
127 self.status(),
128 self.jobs(),
129 self.channel_active(),
130 self.task(),
131 )
132 }
133}
134
135#[macro_export]
136macro_rules! wsupdate {
137 {
138 $worker_state:expr,
139 $receiver:expr,
140 $task:expr,
141 $status:expr$(,)?
142 } => {
143 $worker_state.update($receiver.sender_strong_count(), String::from($task), $receiver.len(), $status)
144 };
145}
146
147#[macro_export]
148macro_rules! wsupdate_async {
149 ($worker_state:expr, $rx:expr$(,)?) => {
150 async {
151 loop {
152 $crate::wsupdate! {
153 $worker_state,
154 $rx,
155 String::from("Processing"),
156 $crate::WorkerStatus::Running,
157 }
158 ::tokio::time::sleep(::core::time::Duration::from_millis(250)).await;
159 }
160 }
161 };
162}