ic_timers/snapshot/
mod.rs1mod identity;
7mod metrics;
8mod model;
9
10pub use identity::{
11 MAX_TIMER_LABEL_BYTES, TimerIdentity, TimerIdentityError, TimerIdentityField, TimerLabel,
12 TimerLabelError,
13};
14pub use metrics::{
15 MeasurementSummary, TimerCounters, TimerObservabilitySnapshot, TimerPerformance,
16};
17pub use model::{
18 DeclarationLifetime, InactiveReason, OrdinaryRuntimeStateSnapshot, TimerCompletion,
19 TimerCompletionOutcome, TimerControlFailure, TimerDirectiveSnapshot, TimerEpoch,
20 TimerLastOutcome, TimerOutcomeSnapshot, TimerPolicy, TimerProcessCondition,
21 TimerRegistrationStatus, TimerRunResult, TimerRuntimeStateSnapshot, TimerSchedulingMode,
22 WatchdogAttemptSnapshot, WatchdogAttemptStatus, WatchdogDecision, WatchdogRunResult,
23 WatchdogRuntimeStateSnapshot,
24};
25
26#[derive(Clone, Debug, Eq, PartialEq)]
28pub struct TimerSnapshot {
29 identity: TimerIdentity,
30 policy: TimerPolicy,
31 lifetime: DeclarationLifetime,
32 state: TimerRuntimeStateSnapshot,
33 scheduling_mode: TimerSchedulingMode,
34 latest_directive: Option<TimerDirectiveSnapshot>,
35 latest_requested_delay_ns: Option<u64>,
36 latest_armed_delay_ns: Option<u64>,
37 observability: TimerObservabilitySnapshot,
38}
39
40impl TimerSnapshot {
41 #[allow(clippy::too_many_arguments)]
42 pub(crate) const fn new(
43 identity: TimerIdentity,
44 policy: TimerPolicy,
45 lifetime: DeclarationLifetime,
46 state: TimerRuntimeStateSnapshot,
47 scheduling_mode: TimerSchedulingMode,
48 latest_directive: Option<TimerDirectiveSnapshot>,
49 latest_requested_delay_ns: Option<u64>,
50 latest_armed_delay_ns: Option<u64>,
51 observability: &TimerObservabilitySnapshot,
52 ) -> Self {
53 Self {
54 identity,
55 policy,
56 lifetime,
57 state,
58 scheduling_mode,
59 latest_directive,
60 latest_requested_delay_ns,
61 latest_armed_delay_ns,
62 observability: *observability,
63 }
64 }
65
66 #[must_use]
68 pub const fn identity(&self) -> &TimerIdentity {
69 &self.identity
70 }
71
72 #[must_use]
74 pub const fn policy(&self) -> TimerPolicy {
75 self.policy
76 }
77
78 #[must_use]
80 pub const fn lifetime(&self) -> DeclarationLifetime {
81 self.lifetime
82 }
83
84 #[must_use]
86 pub const fn state(&self) -> TimerRuntimeStateSnapshot {
87 self.state
88 }
89
90 #[must_use]
92 pub const fn scheduling_mode(&self) -> TimerSchedulingMode {
93 self.scheduling_mode
94 }
95
96 #[must_use]
98 pub const fn latest_directive(&self) -> Option<TimerDirectiveSnapshot> {
99 self.latest_directive
100 }
101
102 #[must_use]
104 pub const fn latest_requested_delay_ns(&self) -> Option<u64> {
105 self.latest_requested_delay_ns
106 }
107
108 #[must_use]
110 pub const fn latest_armed_delay_ns(&self) -> Option<u64> {
111 self.latest_armed_delay_ns
112 }
113
114 #[must_use]
116 pub const fn next_deadline_ns(&self) -> Option<u64> {
117 self.state.next_deadline_ns()
118 }
119
120 #[must_use]
122 pub fn registration_status(&self) -> TimerRegistrationStatus {
123 self.state.into()
124 }
125
126 #[must_use]
128 pub const fn process_condition(&self) -> TimerProcessCondition {
129 match self.state {
130 TimerRuntimeStateSnapshot::Inactive {
131 reason: InactiveReason::Cancelled,
132 } => TimerProcessCondition::Disabled,
133 TimerRuntimeStateSnapshot::Inactive {
134 reason: InactiveReason::InvariantFailure | InactiveReason::ControlFailure(_),
135 } => TimerProcessCondition::Failed,
136 TimerRuntimeStateSnapshot::Inactive {
137 reason: InactiveReason::Stopped,
138 } if matches!(
139 self.observability.outcomes().last_outcome(),
140 Some(TimerLastOutcome::Completed(
141 TimerCompletionOutcome::RetryableFailure
142 ))
143 ) =>
144 {
145 TimerProcessCondition::Failed
146 }
147 TimerRuntimeStateSnapshot::Inactive { .. } => TimerProcessCondition::Idle,
148 TimerRuntimeStateSnapshot::Ordinary(_) | TimerRuntimeStateSnapshot::Watchdog(_)
149 if matches!(self.scheduling_mode, TimerSchedulingMode::Retry) =>
150 {
151 TimerProcessCondition::Retrying
152 }
153 TimerRuntimeStateSnapshot::Ordinary(_) | TimerRuntimeStateSnapshot::Watchdog(_) => {
154 TimerProcessCondition::Active
155 }
156 }
157 }
158
159 #[must_use]
161 pub const fn generation(&self) -> Option<u64> {
162 match self.state {
163 TimerRuntimeStateSnapshot::Inactive { .. } => None,
164 TimerRuntimeStateSnapshot::Ordinary(
165 OrdinaryRuntimeStateSnapshot::Scheduled { generation, .. }
166 | OrdinaryRuntimeStateSnapshot::Running { generation },
167 ) => Some(generation),
168 TimerRuntimeStateSnapshot::Watchdog(WatchdogRuntimeStateSnapshot::Scheduled {
169 scheduler_generation,
170 ..
171 }) => Some(scheduler_generation),
172 TimerRuntimeStateSnapshot::Watchdog(WatchdogRuntimeStateSnapshot::AwaitingWork {
173 successor_generation,
174 ..
175 }) => Some(successor_generation),
176 }
177 }
178
179 #[must_use]
181 pub const fn observability(&self) -> TimerObservabilitySnapshot {
182 self.observability
183 }
184
185 #[must_use]
187 pub const fn consecutive_expected_failures(&self) -> u64 {
188 self.observability.consecutive_expected_failures()
189 }
190}
191
192#[cfg(test)]
193mod tests;