1pub fn compute_unique_key(
6 kind: &str,
7 queue: Option<&str>,
8 args: Option<&serde_json::Value>,
9 period_bucket: Option<i64>,
10) -> Vec<u8> {
11 let mut hasher = blake3::Hasher::new();
12 hasher.update(kind.as_bytes());
13
14 if let Some(queue) = queue {
15 hasher.update(b"\x00");
16 hasher.update(queue.as_bytes());
17 }
18
19 if let Some(args) = args {
20 hasher.update(b"\x00");
21 let canonical = serde_json::to_vec(args).expect("JSON serialization should not fail");
26 hasher.update(&canonical);
27 }
28
29 if let Some(period_bucket) = period_bucket {
30 hasher.update(b"\x00");
31 hasher.update(&period_bucket.to_le_bytes());
32 }
33
34 hasher.finalize().as_bytes()[..16].to_vec()
35}
36
37#[cfg(test)]
38mod tests {
39 use super::*;
40
41 #[test]
42 fn test_unique_key_deterministic() {
43 let key1 = compute_unique_key("send_email", None, None, None);
44 let key2 = compute_unique_key("send_email", None, None, None);
45 assert_eq!(key1, key2);
46 assert_eq!(key1.len(), 16);
47 }
48
49 #[test]
50 fn test_unique_key_different_kinds() {
51 let key1 = compute_unique_key("send_email", None, None, None);
52 let key2 = compute_unique_key("process_payment", None, None, None);
53 assert_ne!(key1, key2);
54 }
55
56 #[test]
57 fn test_unique_key_with_queue() {
58 let key1 = compute_unique_key("send_email", Some("default"), None, None);
59 let key2 = compute_unique_key("send_email", Some("priority"), None, None);
60 let key3 = compute_unique_key("send_email", None, None, None);
61 assert_ne!(key1, key2);
62 assert_ne!(key1, key3);
63 }
64
65 #[test]
66 fn test_unique_key_with_args() {
67 let args1 = serde_json::json!({"to": "a@b.com"});
68 let args2 = serde_json::json!({"to": "c@d.com"});
69 let key1 = compute_unique_key("send_email", None, Some(&args1), None);
70 let key2 = compute_unique_key("send_email", None, Some(&args2), None);
71 assert_ne!(key1, key2);
72 }
73
74 #[test]
75 fn test_unique_key_with_period() {
76 let key1 = compute_unique_key("send_email", None, None, Some(1000));
77 let key2 = compute_unique_key("send_email", None, None, Some(1001));
78 assert_ne!(key1, key2);
79 }
80}