1mod identity;
7mod metrics;
8mod model;
9
10#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
17pub struct TimerRegistrationId {
18 epoch: TimerEpoch,
19 sequence: u64,
20}
21
22impl TimerRegistrationId {
23 pub(crate) const fn new(epoch: TimerEpoch, sequence: u64) -> Self {
24 Self { epoch, sequence }
25 }
26
27 #[must_use]
29 pub const fn epoch(self) -> TimerEpoch {
30 self.epoch
31 }
32
33 #[must_use]
35 pub const fn sequence(self) -> u64 {
36 self.sequence
37 }
38}
39
40pub use identity::{
41 MAX_TIMER_IDENTITY_COMPONENT_BYTES, TimerIdentity, TimerIdentityError, TimerIdentityField,
42};
43pub use metrics::{
44 MeasurementSummary, MemoryPageExtent, MemoryPageSample, MemoryPageSummary, TimerCounters,
45 TimerObservabilitySnapshot, TimerPerformance,
46};
47pub use model::{
48 DeclarationLifetime, InactiveReason, OrdinaryRuntimeStateSnapshot, TimerCompletion,
49 TimerCompletionOutcome, TimerControlFailure, TimerDirectiveSnapshot, TimerEpoch,
50 TimerLastOutcome, TimerOutcomeSnapshot, TimerPolicy, TimerProcessCondition,
51 TimerRegistrationStatus, TimerRunResult, TimerRuntimeStateSnapshot, TimerSchedulingMode,
52 WatchdogAttemptSnapshot, WatchdogAttemptStatus, WatchdogDecision, WatchdogRunResult,
53 WatchdogRuntimeStateSnapshot,
54};
55
56#[derive(Clone, Debug, Eq, PartialEq)]
62pub struct TimerInventorySnapshot {
63 epoch: TimerEpoch,
64 timers: Vec<TimerSnapshot>,
65}
66
67impl TimerInventorySnapshot {
68 pub(crate) const fn new(epoch: TimerEpoch, timers: Vec<TimerSnapshot>) -> Self {
69 Self { epoch, timers }
70 }
71
72 #[must_use]
74 pub const fn epoch(&self) -> TimerEpoch {
75 self.epoch
76 }
77
78 #[must_use]
80 pub fn timers(&self) -> &[TimerSnapshot] {
81 &self.timers
82 }
83
84 #[must_use]
86 pub fn into_timers(self) -> Vec<TimerSnapshot> {
87 self.timers
88 }
89
90 #[must_use]
92 pub const fn len(&self) -> usize {
93 self.timers.len()
94 }
95
96 #[must_use]
98 pub const fn is_empty(&self) -> bool {
99 self.timers.is_empty()
100 }
101}
102
103#[derive(Clone, Debug, Eq, PartialEq)]
105pub struct TimerSnapshot {
106 identity: TimerIdentity,
107 registration_id: TimerRegistrationId,
108 policy: TimerPolicy,
109 lifetime: DeclarationLifetime,
110 state: TimerRuntimeStateSnapshot,
111 scheduling_mode: TimerSchedulingMode,
112 latest_directive: Option<TimerDirectiveSnapshot>,
113 latest_requested_delay_ns: Option<u64>,
114 latest_armed_delay_ns: Option<u64>,
115 observability: TimerObservabilitySnapshot,
116}
117
118impl TimerSnapshot {
119 #[expect(
120 clippy::too_many_arguments,
121 reason = "Registry-only constructor keeps one coherent boundary."
122 )]
123 pub(crate) const fn new(
124 identity: TimerIdentity,
125 registration_id: TimerRegistrationId,
126 policy: TimerPolicy,
127 lifetime: DeclarationLifetime,
128 state: TimerRuntimeStateSnapshot,
129 scheduling_mode: TimerSchedulingMode,
130 latest_directive: Option<TimerDirectiveSnapshot>,
131 latest_requested_delay_ns: Option<u64>,
132 latest_armed_delay_ns: Option<u64>,
133 observability: &TimerObservabilitySnapshot,
134 ) -> Self {
135 Self {
136 identity,
137 registration_id,
138 policy,
139 lifetime,
140 state,
141 scheduling_mode,
142 latest_directive,
143 latest_requested_delay_ns,
144 latest_armed_delay_ns,
145 observability: *observability,
146 }
147 }
148
149 #[must_use]
151 pub const fn identity(&self) -> &TimerIdentity {
152 &self.identity
153 }
154
155 #[must_use]
162 pub const fn registration_id(&self) -> TimerRegistrationId {
163 self.registration_id
164 }
165
166 #[must_use]
168 pub const fn policy(&self) -> TimerPolicy {
169 self.policy
170 }
171
172 #[must_use]
174 pub const fn lifetime(&self) -> DeclarationLifetime {
175 self.lifetime
176 }
177
178 #[must_use]
180 pub const fn state(&self) -> TimerRuntimeStateSnapshot {
181 self.state
182 }
183
184 #[must_use]
190 pub const fn scheduling_mode(&self) -> TimerSchedulingMode {
191 self.scheduling_mode
192 }
193
194 #[must_use]
200 pub const fn latest_directive(&self) -> Option<TimerDirectiveSnapshot> {
201 self.latest_directive
202 }
203
204 #[must_use]
206 pub const fn latest_requested_delay_ns(&self) -> Option<u64> {
207 self.latest_requested_delay_ns
208 }
209
210 #[must_use]
212 pub const fn latest_armed_delay_ns(&self) -> Option<u64> {
213 self.latest_armed_delay_ns
214 }
215
216 #[must_use]
218 pub const fn next_deadline_ns(&self) -> Option<u64> {
219 self.state.next_deadline_ns()
220 }
221
222 #[must_use]
224 pub fn registration_status(&self) -> TimerRegistrationStatus {
225 self.state.into()
226 }
227
228 #[must_use]
230 pub const fn process_condition(&self) -> TimerProcessCondition {
231 match self.state {
232 TimerRuntimeStateSnapshot::Inactive {
233 reason: InactiveReason::Cancelled,
234 } => TimerProcessCondition::Disabled,
235 TimerRuntimeStateSnapshot::Inactive {
236 reason: InactiveReason::InvariantFailure | InactiveReason::ControlFailure(_),
237 } => TimerProcessCondition::Failed,
238 TimerRuntimeStateSnapshot::Inactive {
239 reason: InactiveReason::Stopped,
240 } if matches!(
241 self.observability.outcomes().last_outcome(),
242 Some(TimerLastOutcome::Completed(
243 TimerCompletionOutcome::RetryableFailure
244 ))
245 ) =>
246 {
247 TimerProcessCondition::Failed
248 }
249 TimerRuntimeStateSnapshot::Inactive { .. } => TimerProcessCondition::Idle,
250 TimerRuntimeStateSnapshot::Ordinary(_) | TimerRuntimeStateSnapshot::Watchdog(_)
251 if matches!(self.scheduling_mode, TimerSchedulingMode::Retry) =>
252 {
253 TimerProcessCondition::Retrying
254 }
255 TimerRuntimeStateSnapshot::Ordinary(_) | TimerRuntimeStateSnapshot::Watchdog(_) => {
256 TimerProcessCondition::Active
257 }
258 }
259 }
260
261 #[must_use]
266 pub const fn generation(&self) -> Option<u64> {
267 match self.state {
268 TimerRuntimeStateSnapshot::Inactive { .. } => None,
269 TimerRuntimeStateSnapshot::Ordinary(
270 OrdinaryRuntimeStateSnapshot::Scheduled { generation, .. }
271 | OrdinaryRuntimeStateSnapshot::Running { generation },
272 ) => Some(generation),
273 TimerRuntimeStateSnapshot::Watchdog(WatchdogRuntimeStateSnapshot::Scheduled {
274 scheduler_generation,
275 ..
276 }) => Some(scheduler_generation),
277 TimerRuntimeStateSnapshot::Watchdog(WatchdogRuntimeStateSnapshot::AwaitingWork {
278 successor_generation,
279 ..
280 }) => Some(successor_generation),
281 }
282 }
283
284 #[must_use]
286 pub const fn observability(&self) -> TimerObservabilitySnapshot {
287 self.observability
288 }
289}
290
291#[cfg(test)]
292mod tests;