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]
96 pub const fn scheduling_mode(&self) -> TimerSchedulingMode {
97 self.scheduling_mode
98 }
99
100 #[must_use]
102 pub const fn latest_directive(&self) -> Option<TimerDirectiveSnapshot> {
103 self.latest_directive
104 }
105
106 #[must_use]
108 pub const fn latest_requested_delay_ns(&self) -> Option<u64> {
109 self.latest_requested_delay_ns
110 }
111
112 #[must_use]
114 pub const fn latest_armed_delay_ns(&self) -> Option<u64> {
115 self.latest_armed_delay_ns
116 }
117
118 #[must_use]
120 pub const fn next_deadline_ns(&self) -> Option<u64> {
121 self.state.next_deadline_ns()
122 }
123
124 #[must_use]
126 pub fn registration_status(&self) -> TimerRegistrationStatus {
127 self.state.into()
128 }
129
130 #[must_use]
132 pub const fn process_condition(&self) -> TimerProcessCondition {
133 match self.state {
134 TimerRuntimeStateSnapshot::Inactive {
135 reason: InactiveReason::Cancelled,
136 } => TimerProcessCondition::Disabled,
137 TimerRuntimeStateSnapshot::Inactive {
138 reason: InactiveReason::InvariantFailure | InactiveReason::ControlFailure(_),
139 } => TimerProcessCondition::Failed,
140 TimerRuntimeStateSnapshot::Inactive {
141 reason: InactiveReason::Stopped,
142 } if matches!(
143 self.observability.outcomes().last_outcome(),
144 Some(TimerLastOutcome::Completed(
145 TimerCompletionOutcome::RetryableFailure
146 ))
147 ) =>
148 {
149 TimerProcessCondition::Failed
150 }
151 TimerRuntimeStateSnapshot::Inactive { .. } => TimerProcessCondition::Idle,
152 TimerRuntimeStateSnapshot::Ordinary(_) | TimerRuntimeStateSnapshot::Watchdog(_)
153 if matches!(self.scheduling_mode, TimerSchedulingMode::Retry) =>
154 {
155 TimerProcessCondition::Retrying
156 }
157 TimerRuntimeStateSnapshot::Ordinary(_) | TimerRuntimeStateSnapshot::Watchdog(_) => {
158 TimerProcessCondition::Active
159 }
160 }
161 }
162
163 #[must_use]
165 pub const fn generation(&self) -> Option<u64> {
166 match self.state {
167 TimerRuntimeStateSnapshot::Inactive { .. } => None,
168 TimerRuntimeStateSnapshot::Ordinary(
169 OrdinaryRuntimeStateSnapshot::Scheduled { generation, .. }
170 | OrdinaryRuntimeStateSnapshot::Running { generation },
171 ) => Some(generation),
172 TimerRuntimeStateSnapshot::Watchdog(WatchdogRuntimeStateSnapshot::Scheduled {
173 scheduler_generation,
174 ..
175 }) => Some(scheduler_generation),
176 TimerRuntimeStateSnapshot::Watchdog(WatchdogRuntimeStateSnapshot::AwaitingWork {
177 successor_generation,
178 ..
179 }) => Some(successor_generation),
180 }
181 }
182
183 #[must_use]
185 pub const fn observability(&self) -> TimerObservabilitySnapshot {
186 self.observability
187 }
188
189 #[must_use]
191 pub const fn consecutive_expected_failures(&self) -> u64 {
192 self.observability.consecutive_expected_failures()
193 }
194}
195
196#[cfg(test)]
197mod tests;