Skip to main content

canic_core/dto/
runtime.rs

1use crate::dto::prelude::*;
2
3pub use crate::domain::runtime::{
4    FailureSeverity, RuntimeCheckStatus, RuntimeDiagnosticSeverity, RuntimeFieldVisibility,
5    RuntimeStateDomainStatus,
6};
7
8pub const RUNTIME_INTROSPECTION_SCHEMA_VERSION: u32 = 1;
9
10//
11// CanicHealthStatus
12//
13
14#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
15pub struct CanicHealthStatus {
16    pub schema_version: u32,
17    pub status: HealthStatus,
18    pub observed_at_ns: Option<u64>,
19    pub checks: Vec<RuntimeCheck>,
20}
21
22//
23// CanicReadinessStatus
24//
25
26#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
27pub struct CanicReadinessStatus {
28    pub schema_version: u32,
29    pub role: Option<String>,
30    pub status: ReadinessStatus,
31    pub observed_at_ns: u64,
32    pub checks: Vec<RuntimeCheck>,
33    pub blockers: Vec<RuntimeDiagnostic>,
34    pub warnings: Vec<RuntimeDiagnostic>,
35}
36
37//
38// CanicRuntimeStatus
39//
40
41#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
42pub struct CanicRuntimeStatus {
43    pub schema_version: u32,
44    pub observed_at_ns: u64,
45    pub canister_id: Principal,
46    pub role: Option<String>,
47    pub root: Option<Principal>,
48    pub network: Option<String>,
49    pub build: RuntimeBuildInfo,
50    pub features: Vec<RuntimeFeatureStatus>,
51    pub topology: Option<RuntimeTopologyStatus>,
52    pub timers: Vec<CanicTimerStatus>,
53    pub state: Option<RuntimeStateSummary>,
54    pub auth: Option<RuntimeAuthStatusSummary>,
55    pub blob_storage: Option<RuntimeBlobStorageStatusSummary>,
56    pub recent_failures: Vec<RecentFailure>,
57    pub visibility: Vec<RuntimeVisibilityEntry>,
58    pub readiness: CanicReadinessStatus,
59    pub status: RuntimeStatus,
60}
61
62//
63// RuntimeBuildInfo
64//
65
66#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
67pub struct RuntimeBuildInfo {
68    pub package_name: String,
69    pub package_version: String,
70    pub canic_version: String,
71    pub canister_version: u64,
72}
73
74//
75// RuntimeCheck
76//
77
78#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
79pub struct RuntimeCheck {
80    pub category: String,
81    pub code: String,
82    pub status: RuntimeCheckStatus,
83    pub subject: String,
84    pub detail: String,
85    pub next: Option<String>,
86    pub source: String,
87}
88
89//
90// RuntimeDiagnostic
91//
92
93#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
94pub struct RuntimeDiagnostic {
95    pub category: String,
96    pub code: String,
97    pub severity: RuntimeDiagnosticSeverity,
98    pub subject: String,
99    pub detail: String,
100    pub next: Option<String>,
101    pub source: String,
102}
103
104//
105// RuntimeFeatureStatus
106//
107
108#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
109pub struct RuntimeFeatureStatus {
110    pub name: String,
111    pub enabled: bool,
112    pub visibility: RuntimeFieldVisibility,
113    pub source: String,
114}
115
116//
117// RuntimeTopologyStatus
118//
119
120#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
121pub struct RuntimeTopologyStatus {
122    pub root: Option<Principal>,
123    pub parent: Option<Principal>,
124    pub subnet: Option<Principal>,
125    pub source: String,
126}
127
128//
129// CanicTimerStatus
130//
131
132#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
133pub struct CanicTimerStatus {
134    pub name: String,
135    pub subsystem: String,
136    pub status: TimerStatus,
137    pub enabled: bool,
138    pub registered: bool,
139    pub last_success_at_ns: Option<u64>,
140    pub last_failure_at_ns: Option<u64>,
141    pub next_due_at_ns: Option<u64>,
142    pub consecutive_failures: u64,
143    pub last_error_code: Option<String>,
144    pub last_error_summary: Option<String>,
145}
146
147//
148// RuntimeStateSummary
149//
150
151#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
152pub struct RuntimeStateSummary {
153    pub manifest_schema_version: u32,
154    pub domains: Vec<RuntimeStateDomainSummary>,
155    pub total_stable_memory_pages: Option<u64>,
156}
157
158//
159// RuntimeStateDomainSummary
160//
161
162#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
163pub struct RuntimeStateDomainSummary {
164    pub domain: String,
165    pub version: u32,
166    pub storage: String,
167    pub memory_id: Option<u8>,
168    pub status: RuntimeStateDomainStatus,
169}
170
171//
172// RuntimeAuthStatusSummary
173//
174
175#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
176pub struct RuntimeAuthStatusSummary {
177    pub auth_features: Vec<RuntimeFeatureStatus>,
178}
179
180//
181// RuntimeBlobStorageStatusSummary
182//
183
184#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
185pub struct RuntimeBlobStorageStatusSummary {
186    pub blob_storage_features: Vec<RuntimeFeatureStatus>,
187}
188
189//
190// RecentFailure
191//
192
193#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
194pub struct RecentFailure {
195    pub occurred_at_ns: u64,
196    pub subsystem: String,
197    pub code: String,
198    pub severity: FailureSeverity,
199    pub summary: String,
200    pub correlation_id: Option<String>,
201    pub redacted: bool,
202}
203
204//
205// RuntimeVisibilityEntry
206//
207
208#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
209pub struct RuntimeVisibilityEntry {
210    pub field: String,
211    pub visibility: RuntimeFieldVisibility,
212}
213
214//
215// Status enums
216//
217
218#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
219#[serde(rename_all = "snake_case")]
220pub enum HealthStatus {
221    #[serde(alias = "Healthy")]
222    Healthy,
223    #[serde(alias = "Degraded")]
224    Degraded,
225    #[serde(alias = "Unhealthy")]
226    Unhealthy,
227    #[serde(alias = "Unknown")]
228    Unknown,
229}
230
231#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
232#[serde(rename_all = "snake_case")]
233pub enum ReadinessStatus {
234    #[serde(alias = "Ready")]
235    Ready,
236    #[serde(alias = "Degraded")]
237    Degraded,
238    #[serde(alias = "NotReady")]
239    NotReady,
240    #[serde(alias = "NotEvaluated")]
241    NotEvaluated,
242}
243
244#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
245#[serde(rename_all = "snake_case")]
246pub enum RuntimeStatus {
247    #[serde(alias = "Ok")]
248    Ok,
249    #[serde(alias = "Degraded")]
250    Degraded,
251    #[serde(alias = "Failing")]
252    Failing,
253    #[serde(alias = "Unknown")]
254    Unknown,
255}
256
257#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
258#[serde(rename_all = "snake_case")]
259pub enum TimerStatus {
260    #[serde(alias = "Healthy")]
261    Healthy,
262    #[serde(alias = "Delayed")]
263    Delayed,
264    #[serde(alias = "Failing")]
265    Failing,
266    #[serde(alias = "Disabled")]
267    Disabled,
268    #[serde(alias = "NotRegistered")]
269    NotRegistered,
270    #[serde(alias = "Unknown")]
271    Unknown,
272}
273
274#[cfg(test)]
275mod tests {
276    use super::*;
277    use candid::{Decode, Encode};
278    use serde::de::DeserializeOwned;
279    use std::fmt::Debug;
280
281    #[test]
282    fn runtime_enums_roundtrip_candid_with_runtime_variant_labels() {
283        assert_enum_candid_contract(HealthStatus::Unknown);
284        assert_enum_candid_contract(ReadinessStatus::NotEvaluated);
285        assert_enum_candid_contract(RuntimeStatus::Failing);
286        assert_enum_candid_contract(TimerStatus::NotRegistered);
287        assert_enum_candid_contract(FailureSeverity::Critical);
288        assert_enum_candid_contract(RuntimeCheckStatus::NotEvaluated);
289        assert_enum_candid_contract(RuntimeDiagnosticSeverity::Unsupported);
290        assert_enum_candid_contract(RuntimeFieldVisibility::OperatorOnly);
291        assert_enum_candid_contract(RuntimeStateDomainStatus::NotEvaluated);
292    }
293
294    fn assert_enum_candid_contract<T>(value: T)
295    where
296        T: CandidType + Clone + Debug + DeserializeOwned + Eq,
297    {
298        let bytes = Encode!(&value).expect("encode runtime enum");
299        let decoded = Decode!(&bytes, T).expect("decode runtime enum");
300
301        assert_eq!(decoded, value);
302    }
303}