vti_common/idempotency/class.rs
1//! [`IdempotencyClass`] — the op-class enum that drives cache TTL.
2
3use serde::{Deserialize, Serialize};
4
5/// Op class for an idempotent route, set explicitly at registration
6/// time (plan **D6**: clarity over cleverness; no heuristic on HTTP
7/// method).
8#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
9pub enum IdempotencyClass {
10 /// Standard create / update / read. Cached for 24 h —
11 /// long retry window for offline-then-online clients.
12 NonDestructive,
13
14 /// Delete / revoke / destructive mutation. Cached for **60 s only**
15 /// so a network-flake retry returns the same outcome but a later
16 /// intentional re-creation under the same UUID isn't silently
17 /// no-op'd against a freshly-deleted target.
18 Destructive,
19}
20
21impl IdempotencyClass {
22 /// Cache lifetime in seconds. Pinned in code rather than config
23 /// to keep the semantic boundary between the two classes obvious
24 /// — operators don't tune it.
25 pub fn ttl_seconds(self) -> u64 {
26 match self {
27 Self::NonDestructive => 24 * 60 * 60,
28 Self::Destructive => 60,
29 }
30 }
31}
32
33#[cfg(test)]
34mod tests {
35 use super::*;
36
37 #[test]
38 fn non_destructive_caches_for_24_hours() {
39 assert_eq!(IdempotencyClass::NonDestructive.ttl_seconds(), 86_400);
40 }
41
42 #[test]
43 fn destructive_caches_for_60_seconds() {
44 assert_eq!(IdempotencyClass::Destructive.ttl_seconds(), 60);
45 }
46}