1use siphasher::sip::SipHasher13;
13use std::hash::Hasher;
14
15fn sip13((key0, key1): (u64, u64), parts: &[&str]) -> u64 {
18 parts
19 .iter()
20 .fold(
21 SipHasher13::new_with_keys(key0, key1),
22 |mut hasher, part| {
23 hasher.write(part.as_bytes());
24 hasher.write_u8(0xff);
25 hasher
26 },
27 )
28 .finish()
29}
30
31pub fn legacy_table_lock_key(table: &str) -> i64 {
36 (sip13((0, 0), &[table]) as i64).wrapping_abs() % i64::MAX
37}
38
39pub fn platform_key(namespace: &str, name: &str) -> i64 {
42 sip13(
43 (
44 u64::from_be_bytes(*b"cufflink"),
45 u64::from_be_bytes(*b"locks\0\0\0"),
46 ),
47 &[namespace, name],
48 ) as i64
49}
50
51pub fn platform_lock_key(table: &str) -> i64 {
53 platform_key("migrate", table)
54}
55
56#[cfg(test)]
57mod tests {
58 use super::*;
59 use std::collections::hash_map::DefaultHasher;
60 use std::hash::Hash;
61
62 fn legacy_runner_key(table: &str) -> i64 {
63 let mut hasher = DefaultHasher::new();
64 table.hash(&mut hasher);
65 (hasher.finish() as i64).abs() % i64::MAX
66 }
67
68 #[test]
69 fn the_legacy_key_is_the_one_the_legacy_runner_derives() {
70 for (table, key) in [
71 ("loan_service.schema_history", 5095852499937019771),
72 ("catalog_service.schema_history", 576944167566361902),
73 ("public.schema_history_deferred", 315364223451433509),
74 ("schema_history", 3568529105731104943),
75 ("", 3476900567878811119),
76 ] {
77 assert_eq!(legacy_table_lock_key(table), key, "{table}");
78 assert_eq!(legacy_runner_key(table), key, "{table}");
79 }
80 }
81
82 #[test]
83 fn a_platform_key_is_its_namespace_and_name_together() {
84 assert_ne!(
85 platform_key("db_roles", "cufflink_acme"),
86 platform_key("migrate", "cufflink_acme")
87 );
88 assert_ne!(platform_key("ab", "c"), platform_key("a", "bc"));
89 }
90
91 #[test]
92 fn the_platform_keys_are_the_ones_every_replica_derives() {
93 assert_eq!(
94 platform_key("db_roles", "cufflink_acme"),
95 7182794317239927779
96 );
97 assert_eq!(
98 platform_lock_key("_cufflink.schema_history"),
99 -1468775211513434424
100 );
101 assert_eq!(
102 platform_lock_key("loan_service.refinery_schema_history"),
103 -8958653408802261385
104 );
105 assert_ne!(
106 platform_lock_key("_cufflink.schema_history"),
107 legacy_table_lock_key("_cufflink.schema_history")
108 );
109 }
110}