Skip to main content

canic_core/dto/
runtime.rs

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