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 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}