Skip to main content

lodestone_types/
workload_class.rs

1use std::error::Error;
2use std::fmt::{self, Display, Formatter};
3
4use serde::{Deserialize, Serialize};
5
6/// The exact scheduling/accounting class selected for one authenticated
7/// request. Resource quantities and scheduler weights remain Core policy and
8/// are deliberately absent from this caller-visible classification.
9#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
10#[serde(rename_all = "snake_case")]
11pub enum WorkloadClassV1 {
12    InteractiveSearch,
13    BatchAnalytics,
14    StreamingIngest,
15    BulkBackfill,
16    InternalMaintenance,
17}
18
19impl WorkloadClassV1 {
20    pub const ALL: [Self; 5] = [
21        Self::InteractiveSearch,
22        Self::BatchAnalytics,
23        Self::StreamingIngest,
24        Self::BulkBackfill,
25        Self::InternalMaintenance,
26    ];
27
28    pub const PUBLIC: [Self; 4] = [
29        Self::InteractiveSearch,
30        Self::BatchAnalytics,
31        Self::StreamingIngest,
32        Self::BulkBackfill,
33    ];
34
35    #[must_use]
36    pub const fn is_public(self) -> bool {
37        !matches!(self, Self::InternalMaintenance)
38    }
39
40    const fn bit(self) -> u8 {
41        match self {
42            Self::InteractiveSearch => 1 << 0,
43            Self::BatchAnalytics => 1 << 1,
44            Self::StreamingIngest => 1 << 2,
45            Self::BulkBackfill => 1 << 3,
46            Self::InternalMaintenance => 1 << 4,
47        }
48    }
49}
50
51/// Copyable projection of the classes admitted by the exact role grants that
52/// authorized one request action. This is reconstructible authentication
53/// context, never a second durable policy authority.
54#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
55pub struct WorkloadClassCapabilitiesV1(u8);
56
57impl WorkloadClassCapabilitiesV1 {
58    #[must_use]
59    pub const fn empty() -> Self {
60        Self(0)
61    }
62
63    pub fn from_public_classes(
64        classes: impl IntoIterator<Item = WorkloadClassV1>,
65    ) -> Result<Self, WorkloadClassCapabilityError> {
66        let mut value = Self::empty();
67        for class in classes {
68            if !class.is_public() {
69                return Err(WorkloadClassCapabilityError::InternalClassAtPublicBoundary);
70            }
71            value.0 |= class.bit();
72        }
73        if value.is_empty() {
74            return Err(WorkloadClassCapabilityError::Empty);
75        }
76        Ok(value)
77    }
78
79    #[must_use]
80    pub const fn allows(self, class: WorkloadClassV1) -> bool {
81        self.0 & class.bit() != 0
82    }
83
84    #[must_use]
85    pub const fn is_empty(self) -> bool {
86        self.0 == 0
87    }
88}
89
90#[derive(Clone, Copy, Debug, Eq, PartialEq)]
91pub enum WorkloadClassCapabilityError {
92    Empty,
93    InternalClassAtPublicBoundary,
94}
95
96impl Display for WorkloadClassCapabilityError {
97    fn fmt(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
98        match self {
99            Self::Empty => formatter.write_str("workload-class capability set is empty"),
100            Self::InternalClassAtPublicBoundary => {
101                formatter.write_str("internal-maintenance class is not a public capability")
102            }
103        }
104    }
105}
106
107impl Error for WorkloadClassCapabilityError {}
108
109#[cfg(test)]
110mod tests {
111    use super::*;
112
113    #[test]
114    fn public_capabilities_are_exact_and_internal_is_refused() -> Result<(), Box<dyn Error>> {
115        let capabilities = WorkloadClassCapabilitiesV1::from_public_classes([
116            WorkloadClassV1::InteractiveSearch,
117            WorkloadClassV1::BulkBackfill,
118        ])?;
119        assert!(capabilities.allows(WorkloadClassV1::InteractiveSearch));
120        assert!(capabilities.allows(WorkloadClassV1::BulkBackfill));
121        assert!(!capabilities.allows(WorkloadClassV1::BatchAnalytics));
122        assert!(!capabilities.allows(WorkloadClassV1::InternalMaintenance));
123        assert_eq!(
124            WorkloadClassCapabilitiesV1::from_public_classes([WorkloadClassV1::InternalMaintenance]),
125            Err(WorkloadClassCapabilityError::InternalClassAtPublicBoundary)
126        );
127        Ok(())
128    }
129}