Skip to main content

sayiir_core/
priority.rs

1//! Task priority levels for execution ordering.
2//!
3//! Priority determines the order in which tasks are picked up by workers.
4//! Lower numeric values indicate higher priority. The default is [`Normal`](Priority::Normal) (3).
5
6use serde::{Deserialize, Serialize};
7
8/// Execution priority for a task.
9///
10/// Lower numeric values are executed first. Workers use this value
11/// (combined with aging) to decide which available task to claim next.
12///
13/// # Examples
14///
15/// ```
16/// use sayiir_core::priority::Priority;
17///
18/// assert_eq!(Priority::default(), Priority::Normal);
19/// assert_eq!(Priority::Critical.as_u8(), 1);
20/// assert!(Priority::Critical < Priority::Low);
21/// ```
22#[repr(u8)]
23#[derive(
24    Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize,
25)]
26pub enum Priority {
27    /// Highest priority (1). Use sparingly for time-critical work.
28    Critical = 1,
29    /// High priority (2).
30    High = 2,
31    /// Default priority (3).
32    #[default]
33    Normal = 3,
34    /// Low priority (4). Background work.
35    Low = 4,
36    /// Lowest priority (5). Best-effort, may be starved without aging.
37    Minimal = 5,
38}
39
40impl Priority {
41    /// Convert a `u8` to a `Priority`, returning `None` for out-of-range values.
42    #[must_use]
43    pub fn from_u8(value: u8) -> Option<Self> {
44        match value {
45            1 => Some(Self::Critical),
46            2 => Some(Self::High),
47            3 => Some(Self::Normal),
48            4 => Some(Self::Low),
49            5 => Some(Self::Minimal),
50            _ => None,
51        }
52    }
53
54    /// Return the numeric value of this priority (1–5).
55    #[must_use]
56    pub fn as_u8(self) -> u8 {
57        self as u8
58    }
59}
60
61#[cfg(test)]
62#[allow(clippy::unwrap_used)]
63mod tests {
64    use super::*;
65
66    #[test]
67    fn default_is_normal() {
68        assert_eq!(Priority::default(), Priority::Normal);
69        assert_eq!(Priority::default().as_u8(), 3);
70    }
71
72    #[test]
73    fn round_trip() {
74        for v in 1..=5 {
75            let p = Priority::from_u8(v).unwrap();
76            assert_eq!(p.as_u8(), v);
77        }
78    }
79
80    #[test]
81    fn out_of_range() {
82        assert!(Priority::from_u8(0).is_none());
83        assert!(Priority::from_u8(6).is_none());
84    }
85
86    #[test]
87    fn ordering() {
88        assert!(Priority::Critical < Priority::High);
89        assert!(Priority::High < Priority::Normal);
90        assert!(Priority::Normal < Priority::Low);
91        assert!(Priority::Low < Priority::Minimal);
92    }
93}