1use std::sync::OnceLock;
6use uuid::Uuid;
7
8static CORRELATION_ID: OnceLock<Uuid> = OnceLock::new();
10
11#[must_use]
16pub fn correlation_id() -> Uuid {
17 *CORRELATION_ID.get_or_init(Uuid::new_v4)
18}
19
20pub fn set_correlation_id(id: Uuid) -> bool {
25 CORRELATION_ID.set(id).is_ok()
26}
27
28#[derive(Debug, Clone)]
32pub struct MetadataContext {
33 pub correlation_id: Uuid,
35 pub default_target: Option<String>,
37}
38
39impl MetadataContext {
40 #[must_use]
42 pub fn new() -> Self {
43 Self {
44 correlation_id: correlation_id(),
45 default_target: None,
46 }
47 }
48
49 #[must_use]
51 pub const fn with_correlation_id(id: Uuid) -> Self {
52 Self {
53 correlation_id: id,
54 default_target: None,
55 }
56 }
57
58 #[must_use]
60 pub fn with_target(mut self, target: impl Into<String>) -> Self {
61 self.default_target = Some(target.into());
62 self
63 }
64}
65
66impl Default for MetadataContext {
67 fn default() -> Self {
68 Self::new()
69 }
70}
71
72#[cfg(test)]
73mod tests {
74 use super::*;
75
76 #[test]
77 fn test_correlation_id_consistency() {
78 let id1 = correlation_id();
79 let id2 = correlation_id();
80 assert_eq!(id1, id2);
81 }
82
83 #[test]
84 fn test_metadata_context_creation() {
85 let ctx = MetadataContext::new();
86 assert!(!ctx.correlation_id.is_nil());
87 assert!(ctx.default_target.is_none());
88 }
89
90 #[test]
91 fn test_metadata_context_with_target() {
92 let ctx = MetadataContext::new().with_target("cuenv::test");
93 assert_eq!(ctx.default_target, Some("cuenv::test".to_string()));
94 }
95
96 #[test]
97 fn test_metadata_context_default() {
98 let ctx = MetadataContext::default();
99 assert!(!ctx.correlation_id.is_nil());
100 assert!(ctx.default_target.is_none());
101 }
102
103 #[test]
104 fn test_metadata_context_with_correlation_id() {
105 let id = Uuid::new_v4();
106 let ctx = MetadataContext::with_correlation_id(id);
107 assert_eq!(ctx.correlation_id, id);
108 assert!(ctx.default_target.is_none());
109 }
110
111 #[test]
112 fn test_metadata_context_debug() {
113 let ctx = MetadataContext::new();
114 let debug = format!("{:?}", ctx);
115 assert!(debug.contains("MetadataContext"));
116 assert!(debug.contains("correlation_id"));
117 }
118
119 #[test]
120 fn test_metadata_context_clone() {
121 let ctx = MetadataContext::new().with_target("test");
122 let cloned = ctx.clone();
123 assert_eq!(ctx.correlation_id, cloned.correlation_id);
124 assert_eq!(ctx.default_target, cloned.default_target);
125 }
126
127 #[test]
128 fn test_metadata_context_with_string_target() {
129 let ctx = MetadataContext::new().with_target(String::from("owned-target"));
130 assert_eq!(ctx.default_target, Some("owned-target".to_string()));
131 }
132
133 #[test]
134 fn test_set_correlation_id_after_init() {
135 let _ = correlation_id(); let new_id = Uuid::new_v4();
138 let result = set_correlation_id(new_id);
139 assert!(!result);
141 }
142}