Skip to main content

rskit_worker/
event.rs

1use chrono::{DateTime, Utc};
2use uuid::Uuid;
3
4/// Kind of event emitted by a worker during task execution.
5#[derive(Debug, Clone, PartialEq, Eq)]
6#[non_exhaustive]
7pub enum EventKind {
8    /// Periodic progress update with completion percentage.
9    Progress,
10    /// A partial result emitted before the task finishes.
11    Partial,
12    /// A free-form log message from the task.
13    Log,
14    /// The final successful result of the task.
15    Result,
16    /// The task failed with this error message.
17    Error,
18}
19
20/// Progress information for a long-running task.
21#[derive(Debug, Clone)]
22pub struct Progress {
23    /// Number of units completed so far.
24    pub current: u64,
25    /// Total number of units, if known.
26    pub total: Option<u64>,
27    /// Completion percentage derived from `current / total`, if `total` is known.
28    pub percent: Option<f32>,
29    /// Optional human-readable status message.
30    pub message: Option<String>,
31}
32
33impl Progress {
34    /// Create a new `Progress` value, computing `percent` when `total` is provided.
35    pub fn new(current: u64, total: Option<u64>) -> Self {
36        let percent = total.map(|t| {
37            if t == 0 {
38                100.0
39            } else {
40                (current as f32 / t as f32) * 100.0
41            }
42        });
43        Self {
44            current,
45            total,
46            percent,
47            message: None,
48        }
49    }
50
51    /// Attach a human-readable status message to this progress value.
52    #[must_use]
53    pub fn with_message(mut self, msg: impl Into<String>) -> Self {
54        self.message = Some(msg.into());
55        self
56    }
57}
58
59/// Event emitted by a worker task on the event channel.
60#[derive(Debug, Clone)]
61pub struct Event<O: Clone> {
62    /// The kind of this event.
63    pub kind: EventKind,
64    /// Identifier of the task that produced this event.
65    pub task_id: Uuid,
66    /// Identifier of the worker that produced this event.
67    pub worker_id: String,
68    /// Progress snapshot, present for `EventKind::Progress` events.
69    pub progress: Option<Progress>,
70    /// Task output payload, present for `Partial` and `Result` events.
71    pub data: Option<O>,
72    /// Error or log message, present for `Error` and `Log` events.
73    pub error: Option<String>,
74    /// Wall-clock time at which the event was created.
75    pub timestamp: DateTime<Utc>,
76}
77
78impl<O: Clone> Event<O> {
79    /// Create a progress event carrying the given [`Progress`] snapshot.
80    pub fn progress(task_id: Uuid, worker_id: impl Into<String>, p: Progress) -> Self {
81        Self {
82            kind: EventKind::Progress,
83            task_id,
84            worker_id: worker_id.into(),
85            progress: Some(p),
86            data: None,
87            error: None,
88            timestamp: Utc::now(),
89        }
90    }
91
92    /// Create a partial-result event carrying an intermediate output value.
93    pub fn partial(task_id: Uuid, worker_id: impl Into<String>, data: O) -> Self {
94        Self {
95            kind: EventKind::Partial,
96            task_id,
97            worker_id: worker_id.into(),
98            progress: None,
99            data: Some(data),
100            error: None,
101            timestamp: Utc::now(),
102        }
103    }
104
105    /// Create a log event carrying a free-form text message.
106    pub fn log(task_id: Uuid, worker_id: impl Into<String>, message: impl Into<String>) -> Self {
107        Self {
108            kind: EventKind::Log,
109            task_id,
110            worker_id: worker_id.into(),
111            progress: None,
112            data: None,
113            error: Some(message.into()),
114            timestamp: Utc::now(),
115        }
116    }
117
118    /// Create a final-result event carrying the successful task output.
119    pub fn result(task_id: Uuid, worker_id: impl Into<String>, data: O) -> Self {
120        Self {
121            kind: EventKind::Result,
122            task_id,
123            worker_id: worker_id.into(),
124            progress: None,
125            data: Some(data),
126            error: None,
127            timestamp: Utc::now(),
128        }
129    }
130
131    /// Create an error event carrying the failure message.
132    pub fn error(task_id: Uuid, worker_id: impl Into<String>, err: impl Into<String>) -> Self {
133        Self {
134            kind: EventKind::Error,
135            task_id,
136            worker_id: worker_id.into(),
137            progress: None,
138            data: None,
139            error: Some(err.into()),
140            timestamp: Utc::now(),
141        }
142    }
143}