1use serde::{Deserialize, Serialize};
17use std::fmt;
18use uuid::Uuid;
19use xxhash_rust::xxh3::xxh3_64;
20
21#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
29#[serde(transparent)]
30pub struct InstanceId(Uuid);
31
32impl InstanceId {
33 pub fn new_v4() -> Self {
38 loop {
39 let instance_id = InstanceId(Uuid::new_v4());
40 let worker_id = WorkerId::from(&instance_id);
41 if worker_id.as_u64() != 0 {
42 return instance_id;
43 }
44 }
45 }
46
47 pub fn worker_id(&self) -> WorkerId {
52 WorkerId::from(self)
53 }
54
55 pub fn as_uuid(&self) -> &Uuid {
57 &self.0
58 }
59
60 pub fn as_u128(&self) -> u128 {
62 self.0.as_u128()
63 }
64
65 pub fn as_bytes(&self) -> &[u8; 16] {
67 self.0.as_bytes()
68 }
69}
70
71impl fmt::Display for InstanceId {
72 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
73 write!(f, "{}", self.0)
74 }
75}
76
77impl From<Uuid> for InstanceId {
78 fn from(uuid: Uuid) -> Self {
79 Self(uuid)
80 }
81}
82
83impl From<InstanceId> for Uuid {
84 fn from(id: InstanceId) -> Self {
85 id.0
86 }
87}
88
89impl AsRef<Uuid> for InstanceId {
90 fn as_ref(&self) -> &Uuid {
91 &self.0
92 }
93}
94
95#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, PartialOrd, Ord)]
122#[serde(transparent)]
123pub struct WorkerId(u64);
124
125impl WorkerId {
126 pub fn from_u64(value: u64) -> Self {
131 Self(value)
132 }
133
134 #[inline(always)]
136 pub fn as_u64(&self) -> u64 {
137 self.0
138 }
139}
140
141impl fmt::Display for WorkerId {
142 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
143 write!(f, "{}", self.0)
144 }
145}
146
147impl From<&InstanceId> for WorkerId {
148 fn from(id: &InstanceId) -> Self {
153 Self(xxh3_64(id.as_uuid().as_bytes()))
154 }
155}
156
157impl From<InstanceId> for WorkerId {
158 fn from(id: InstanceId) -> Self {
159 Self::from(&id)
160 }
161}
162
163impl From<WorkerId> for u64 {
164 fn from(id: WorkerId) -> Self {
165 id.0
166 }
167}
168
169#[cfg(test)]
170mod tests {
171 use super::*;
172
173 #[test]
174 fn test_instance_id_creation() {
175 let id1 = InstanceId::new_v4();
176 let id2 = InstanceId::new_v4();
177
178 assert_ne!(id1, id2);
180
181 let uuid: Uuid = id1.into();
183 let id3 = InstanceId::from(uuid);
184 assert_eq!(id1, id3);
185 }
186
187 #[test]
188 fn test_worker_id_deterministic() {
189 let instance_id = InstanceId::new_v4();
190
191 let worker_id1 = instance_id.worker_id();
193 let worker_id2 = instance_id.worker_id();
194 assert_eq!(worker_id1, worker_id2);
195
196 let other_instance = InstanceId::new_v4();
198 let other_worker = other_instance.worker_id();
199 assert_ne!(worker_id1, other_worker);
200 }
201
202 #[test]
203 fn test_worker_id_from_conversion() {
204 let instance_id = InstanceId::new_v4();
205
206 let worker_id1 = WorkerId::from(&instance_id);
208 let worker_id2 = WorkerId::from(instance_id);
209 assert_eq!(worker_id1, worker_id2);
210
211 assert_eq!(worker_id1, instance_id.worker_id());
213 }
214
215 #[test]
216 fn test_instance_id_display() {
217 let instance_id = InstanceId::new_v4();
218 let display = format!("{}", instance_id);
219 let uuid_display = format!("{}", instance_id.as_uuid());
220 assert_eq!(display, uuid_display);
221 }
222
223 #[test]
224 fn test_worker_id_display() {
225 let instance_id = InstanceId::new_v4();
226 let worker_id = instance_id.worker_id();
227 let display = format!("{}", worker_id);
228 let u64_display = format!("{}", worker_id.as_u64());
229 assert_eq!(display, u64_display);
230 }
231
232 #[test]
233 fn test_instance_id_serde() {
234 let instance_id = InstanceId::new_v4();
235
236 let json = serde_json::to_string(&instance_id).unwrap();
238
239 let uuid_json = serde_json::to_string(instance_id.as_uuid()).unwrap();
241 assert_eq!(json, uuid_json);
242
243 let deserialized: InstanceId = serde_json::from_str(&json).unwrap();
245 assert_eq!(instance_id, deserialized);
246 }
247
248 #[test]
249 fn test_worker_id_serde() {
250 let worker_id = InstanceId::new_v4().worker_id();
251
252 let json = serde_json::to_string(&worker_id).unwrap();
254
255 let u64_json = serde_json::to_string(&worker_id.as_u64()).unwrap();
257 assert_eq!(json, u64_json);
258
259 let deserialized: WorkerId = serde_json::from_str(&json).unwrap();
261 assert_eq!(worker_id, deserialized);
262 }
263
264 #[test]
265 fn test_worker_id_u64_conversion() {
266 let instance_id = InstanceId::new_v4();
267 let worker_id = instance_id.worker_id();
268
269 let raw_u64 = worker_id.as_u64();
270 let reconstructed = WorkerId::from_u64(raw_u64);
271
272 assert_eq!(worker_id, reconstructed);
273 }
274}