Skip to main content

harn_vm/triggers/worker_queue/
scheduling.rs

1use serde::{Deserialize, Serialize};
2
3pub(super) const NORMAL_PROMOTION_AGE_MS: i64 = 15 * 60 * 1000;
4
5/// Maximum time deferrable work remains below higher-priority work.
6pub const DEFERRABLE_PROMOTION_AGE_MS: i64 = 30 * 60 * 1000;
7
8#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
9#[serde(rename_all = "lowercase")]
10pub enum WorkerQueuePriority {
11    High,
12    #[default]
13    Normal,
14    Low,
15}
16
17impl WorkerQueuePriority {
18    pub fn as_str(self) -> &'static str {
19        match self {
20            Self::High => "high",
21            Self::Normal => "normal",
22            Self::Low => "low",
23        }
24    }
25
26    pub fn effective_rank(self, enqueued_at_ms: i64, now_ms: i64) -> u8 {
27        match self {
28            Self::High => 0,
29            Self::Normal if now_ms.saturating_sub(enqueued_at_ms) >= NORMAL_PROMOTION_AGE_MS => 0,
30            Self::Normal => 1,
31            Self::Low if now_ms.saturating_sub(enqueued_at_ms) >= DEFERRABLE_PROMOTION_AGE_MS => 0,
32            Self::Low => 2,
33        }
34    }
35
36    pub fn promotion_deadline_at_ms(self, enqueued_at_ms: i64) -> Option<i64> {
37        match self {
38            Self::High => None,
39            Self::Normal => Some(enqueued_at_ms.saturating_add(NORMAL_PROMOTION_AGE_MS)),
40            Self::Low => Some(enqueued_at_ms.saturating_add(DEFERRABLE_PROMOTION_AGE_MS)),
41        }
42    }
43
44    pub fn deadline_promoted(self, enqueued_at_ms: i64, now_ms: i64) -> bool {
45        self.promotion_deadline_at_ms(enqueued_at_ms)
46            .is_some_and(|deadline| now_ms >= deadline)
47    }
48
49    pub(in crate::triggers) fn selection_rank(self, enqueued_at_ms: i64, now_ms: i64) -> (u8, u8) {
50        (
51            u8::from(!self.deadline_promoted(enqueued_at_ms, now_ms)),
52            self.effective_rank(enqueued_at_ms, now_ms),
53        )
54    }
55}
56
57#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
58#[serde(rename_all = "kebab-case")]
59pub enum WorkerQueueSchedulingDecision {
60    Priority,
61    FairShare,
62    StarvationDeadline,
63}
64
65/// Typed evidence for the scheduler decision that produced a claim.
66#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
67pub struct WorkerQueueSchedulingReceipt {
68    pub selected_at_ms: i64,
69    pub enqueued_at_ms: i64,
70    pub waited_ms: u64,
71    pub priority: WorkerQueuePriority,
72    pub decision: WorkerQueueSchedulingDecision,
73    pub promotion_deadline_at_ms: Option<i64>,
74    pub fairness_key: String,
75}