Skip to main content

crankshaft_events/
lib.rs

1//! Definition of the events broadcast by Crankshaft.
2
3use std::process::ExitStatus;
4use std::sync::atomic::AtomicU64;
5use std::sync::atomic::Ordering;
6
7use bytes::Bytes;
8use nonempty::NonEmpty;
9use tokio_util::sync::CancellationToken;
10
11/// Represents a Crankshaft task identifier.
12pub type TaskId = u64;
13
14/// Gets the next task id.
15pub fn next_task_id() -> TaskId {
16    static NEXT_TASK_ID: AtomicU64 = AtomicU64::new(0);
17    NEXT_TASK_ID.fetch_add(1, Ordering::SeqCst)
18}
19
20/// An event sent by task execution backends.
21#[derive(Debug, Clone)]
22pub enum Event {
23    /// A task has been created.
24    ///
25    /// Note: a task is not "running" until the [`Event::TaskStarted`] event.
26    ///
27    /// This event is always paired with a `TaskCompleted`, `TaskFailed`,
28    /// `TaskCanceled`, or `TaskPreempted` event.
29    TaskCreated {
30        /// The id of the task.
31        id: TaskId,
32        /// The name of the task.
33        ///
34        /// This may be a display name provided by the user or a name provided
35        /// by the backend if the user did not provide a name for the task.
36        name: String,
37        /// The TES identifier of the task.
38        ///
39        /// This is `Some` only for the TES backend.
40        tes_id: Option<String>,
41
42        /// The cancellation token provided by the backend
43        token: CancellationToken,
44    },
45    /// A task has started execution.
46    ///
47    /// A task is considered "running" upon the receipt of this event.
48    TaskStarted {
49        /// The id of the task.
50        id: TaskId,
51    },
52    /// A container has been created for a task.
53    ///
54    /// This event is only sent by the Docker backend.
55    TaskContainerCreated {
56        /// The id of the task.
57        id: TaskId,
58        /// The name of the container that was created.
59        container: String,
60    },
61    /// A container has exited for a task.
62    ///
63    /// This event is only sent by the Docker backend.
64    TaskContainerExited {
65        /// The id of the task.
66        id: TaskId,
67        /// The name of the container that has exited.
68        container: String,
69        /// The exit status of the container.
70        exit_status: ExitStatus,
71    },
72    /// A task has completed.
73    ///
74    /// This event occurs after all task executions have completed successfully.
75    TaskCompleted {
76        /// The id of the task.
77        id: TaskId,
78        /// The exit statuses for the task's executions.
79        exit_statuses: NonEmpty<ExitStatus>,
80    },
81    /// A task has failed.
82    ///
83    /// This event occurs after any error encountered running a task.
84    TaskFailed {
85        /// The id of the task.
86        id: TaskId,
87        /// The error message.
88        message: String,
89    },
90    /// A task has been canceled.
91    TaskCanceled {
92        /// The id of the task.
93        id: TaskId,
94    },
95    /// The task was preempted.
96    TaskPreempted {
97        /// The id of the task.
98        id: TaskId,
99    },
100    /// A task has logged stdout.
101    ///
102    /// Note: only locally executing tasks will send this event.
103    TaskStdout {
104        /// The id of the task.
105        id: TaskId,
106        /// The bytes logged to stdout.
107        message: Bytes,
108    },
109    /// A task has logged stderr.
110    ///
111    /// Note: only locally executing tasks will send this event.
112    TaskStderr {
113        /// The id of the task.
114        id: TaskId,
115        /// The bytes logged to stdout.
116        message: Bytes,
117    },
118    /// A container image pull was started.
119    ///
120    /// ## Implementation Notes
121    ///
122    /// * This event indicates that an actual fetch process is initiated.
123    ///   Backends **should not** emit this if the image is already present.
124    /// * Backends *may* emit this event multiple times for the same image if
125    ///   multiple executions request it.
126    ///
127    /// This event is always paired with either an [`Event::ImagePullFinished`]
128    /// or [`Event::ImagePullFailed`] event.
129    ImagePullStarted {
130        /// The id of the task that triggered the pull.
131        id: TaskId,
132        /// The name of the image being pulled.
133        name: String,
134    },
135    /// Failed to pull a container image.
136    ///
137    /// Note: This indicates the termination of an image pull. It **will not**
138    /// be paired with an [`Event::ImagePullFinished`] event.
139    ImagePullFailed {
140        /// The id of the task that triggered the pull.
141        id: TaskId,
142        /// The name of the image that failed.
143        name: String,
144        /// The error message.
145        message: String,
146    },
147    /// A container image was successfully pulled.
148    ImagePullFinished {
149        /// The id of the task that triggered the pull.
150        id: TaskId,
151        /// The name of the image that was pulled.
152        name: String,
153    },
154}
155
156/// Sends an event through a broadcast channel.
157///
158/// If the sender is `None`, the event expression is not evaluated and no event
159/// is sent.
160#[macro_export]
161macro_rules! send_event {
162    ($sender:expr, $event:expr $(,)?) => {
163        if let Some(sender) = &$sender {
164            sender.send($event).ok();
165        }
166    };
167}