ruva_core/
snowflake.rs

1#![allow(dead_code)]
2//! This is to generate global identifier
3
4use std::hint::spin_loop;
5use std::ops::Deref;
6use std::sync::atomic::{AtomicI16, AtomicI64, Ordering};
7
8use std::time::{SystemTime, UNIX_EPOCH};
9
10use serde::de::Visitor;
11use serde::{de, Serialize, Serializer};
12
13#[derive(Debug)]
14pub struct NumericalUniqueIdGenerator {
15	/// epoch used by the snowflake algorithm.
16	epoch: SystemTime,
17
18	/// datacenter_id and machine_id are fixed once the system is up running.
19	/// Any changes in datacenter IDs require careful review since an accidental change in those values can lead to ID conflicts
20	/// make sure that none of them is bigger than 5bits
21	pub datacenter_id: i32,
22	pub machine_id: i32,
23
24	/// Most important 41 bits make up the timestamp section. As timestamps grow with time, IDs are sortable by time.
25	/// Maximum timestamp that can be represented in 41 bits is 2^41 -1 = 2199023255551 give is around 69 years.
26	timestamp: AtomicI64,
27
28	/// Sequence number is 12 bits, give gives us 2^12 combinations. This field is 0 unless more than one ID is generated in a millisecond on the same server
29	sequence_num: AtomicI16,
30}
31
32#[derive(Debug)]
33pub struct NumericalUniqueIdBucket {
34	/// Hidden the `NumericalUniqueIdGenerator` in bucket .
35	snowflake_id_generator: NumericalUniqueIdGenerator,
36
37	/// The bucket buffer;
38	bucket: Vec<i64>,
39}
40
41impl NumericalUniqueIdGenerator {
42	/// Constructs a new `NumericalUniqueIdGenerator` using the UNIX epoch.
43	///
44	/// # Examples
45	///
46	/// ```
47	/// use snowflake::NumericalUniqueIdGenerator;
48	///
49	/// let id_generator = NumericalUniqueIdGenerator::new(1, 1);
50	/// ```
51	pub fn new(datacenter_id: i32, machine_id: i32) -> NumericalUniqueIdGenerator {
52		Self::with_epoch(datacenter_id, machine_id, UNIX_EPOCH)
53	}
54
55	/// Constructs a new `NumericalUniqueIdGenerator` using the specified epoch.
56	///
57	/// # Examples
58	///
59	/// ```
60	/// use std::time::{Duration, UNIX_EPOCH};
61	/// use snowflake::NumericalUniqueIdGenerator;
62	///
63	/// // 1 January 2015 00:00:00
64	/// let discord_epoch = UNIX_EPOCH + Duration::from_millis(1420070400000);
65	/// let id_generator = NumericalUniqueIdGenerator::with_epoch(1, 1, discord_epoch);
66	/// ```
67	pub fn with_epoch(datacenter_id: i32, machine_id: i32, epoch: SystemTime) -> NumericalUniqueIdGenerator {
68		//TODO:limit the maximum of input args datacenter_id and machine_id
69		let timestamp = current_time_in_milli(epoch);
70
71		NumericalUniqueIdGenerator {
72			epoch,
73			timestamp: AtomicI64::new(timestamp),
74			datacenter_id,
75			machine_id,
76			sequence_num: AtomicI16::new(0),
77		}
78	}
79
80	/// within 64 bits:
81	/// sign bit and timestamp takes 42 bits so, left shift 22
82	/// datacenter id takes 5 bits in the second place so left shift 17
83	/// machine id takes 5 bits in the third place so left shift 12
84	/// sequence number comes last.
85	fn get_snowflake(&self) -> i64 {
86		self.timestamp.load(Ordering::Relaxed) << 22 | ((self.datacenter_id << 17) as i64) | ((self.machine_id << 12) as i64) | (self.sequence_num.load(Ordering::Relaxed) as i64)
87	}
88
89	/// The basic guarantee time punctuality.
90	///
91	/// Basic guarantee time punctuality.
92
93	/// When traffic peaks, 4096 in a millsec is simply not enough.
94	/// But setting time after every 4096 calls.
95	///
96	/// # Examples
97	///
98	/// ```
99	/// use snowflake::NumericalUniqueIdGenerator;
100	///
101	/// let mut id_generator = NumericalUniqueIdGenerator::new(1, 1);
102	/// id_generator.generate();
103	/// ```
104	pub fn generate(&self) -> i64 {
105		self.sequence_num.store((self.sequence_num.load(Ordering::Relaxed) + 1) % 4096, Ordering::Relaxed);
106
107		let mut now_millis = current_time_in_milli(self.epoch);
108
109		// If the following is true, then check if sequence has been created 4092 times,
110		// and then busy wait until the next millisecond
111		// to prevent 'clock is moving backwards' situation.
112		if self.timestamp.load(Ordering::Relaxed) == now_millis {
113			// Maintenance `timestamp` for every 4096 ids generated.
114			if self.sequence_num.load(Ordering::Relaxed) == 0 {
115				now_millis = race_next_milli(self.timestamp.load(Ordering::Relaxed), self.epoch);
116				self.timestamp.store(now_millis, Ordering::Relaxed);
117			}
118		} else {
119			self.timestamp.store(now_millis, Ordering::Relaxed);
120			self.sequence_num.store(0, Ordering::Relaxed);
121		}
122
123		self.get_snowflake()
124	}
125}
126
127// TODO Get the following concept
128impl NumericalUniqueIdBucket {
129	/// Constructs a new `NumericalUniqueIdBucket` using the UNIX epoch.
130	/// Please make sure that datacenter_id and machine_id is small than 32(2^5);
131	///
132	/// # Examples
133	///
134	/// ```
135	/// use snowflake::NumericalUniqueIdBucket;
136	///
137	/// let id_generator_bucket = NumericalUniqueIdBucket::new(1, 1);
138	/// ```
139	pub fn new(datacenter_id: i32, machine_id: i32) -> Self {
140		Self::with_epoch(datacenter_id, machine_id, UNIX_EPOCH)
141	}
142
143	/// Constructs a new `NumericalUniqueIdBucket` using the specified epoch.
144	/// Please make sure that datacenter_id and machine_id is small than 32(2^5);
145	///
146	/// # Examples
147	///
148	/// ```
149	/// use std::time::{Duration, UNIX_EPOCH};
150	/// use snowflake::NumericalUniqueIdBucket;
151	///
152	/// // 1 January 2015 00:00:00
153	/// let beringlab = UNIX_EPOCH + Duration::from_millis(1570292856000);
154	/// let id_generator_bucket = NumericalUniqueIdBucket::with_epoch(1, 1, beringlab);
155	/// ```
156	pub fn with_epoch(datacenter_id: i32, machine_id: i32, epoch: SystemTime) -> Self {
157		let snowflake_id_generator = NumericalUniqueIdGenerator::with_epoch(datacenter_id, machine_id, epoch);
158		let bucket = Vec::new();
159
160		NumericalUniqueIdBucket { snowflake_id_generator, bucket }
161	}
162
163	/// # Examples
164	///
165	/// ```
166	/// use snowflake::NumericalUniqueIdBucket;
167	///
168	/// let mut id_generator_bucket = NumericalUniqueIdBucket::new(1, 1);
169	/// let id = id_generator_bucket.get_id();
170	///
171	/// ```
172	pub fn get_id(&mut self) -> i64 {
173		// 247 ns/iter
174		// after self.bucket.push(self.snowflake_id_generator.generate());
175
176		if self.bucket.is_empty() {
177			self.fill_bucket();
178		}
179		self.bucket.pop().unwrap()
180	}
181
182	fn fill_bucket(&mut self) {
183		// 1,107,103 -- 1,035,018 ns/iter
184		//self.bucket.push(self.snowflake_id_generator.generate());
185
186		for _ in 0..4091 {
187			self.bucket.push(self.snowflake_id_generator.generate());
188		}
189	}
190}
191
192#[inline(always)]
193/// Get the latest milliseconds of the clock.
194pub fn current_time_in_milli(epoch: SystemTime) -> i64 {
195	SystemTime::now().duration_since(epoch).expect("System Time Error!").as_millis() as i64
196}
197
198#[inline(always)]
199// Constantly refreshing the latest milliseconds by busy waiting.
200fn race_next_milli(timestamp: i64, epoch: SystemTime) -> i64 {
201	let mut latest_time_millis: i64;
202	loop {
203		latest_time_millis = current_time_in_milli(epoch);
204		if latest_time_millis > timestamp {
205			return latest_time_millis;
206		}
207		spin_loop();
208	}
209}
210
211static ID_GENERATOR: std::sync::LazyLock<NumericalUniqueIdGenerator> = std::sync::LazyLock::new(|| {
212	NumericalUniqueIdGenerator::new(
213		std::env::var("DATACENTER_ID").unwrap_or("1".to_string()).parse::<i32>().expect("Parsing Failed!"),
214		std::env::var("MACHINE_ID").unwrap_or("1".to_string()).parse::<i32>().expect("Parsing Failed!"),
215	)
216});
217
218#[derive(Clone, Hash, PartialEq, Debug, Eq, Ord, PartialOrd, Copy, Default)]
219pub struct SnowFlake(pub i64);
220impl SnowFlake {
221	pub fn generate() -> Self {
222		ID_GENERATOR.generate().into()
223	}
224}
225
226impl Deref for SnowFlake {
227	type Target = i64;
228
229	fn deref(&self) -> &Self::Target {
230		&self.0
231	}
232}
233
234impl From<i64> for SnowFlake {
235	fn from(value: i64) -> Self {
236		Self(value)
237	}
238}
239
240impl From<SnowFlake> for String {
241	fn from(value: SnowFlake) -> Self {
242		value.0.to_string()
243	}
244}
245
246impl From<SnowFlake> for i64 {
247	fn from(value: SnowFlake) -> Self {
248		value.0
249	}
250}
251
252impl std::fmt::Display for SnowFlake {
253	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
254		write!(f, "{}", self.0)
255	}
256}
257
258impl<'de> serde::Deserialize<'de> for SnowFlake {
259	fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
260	where
261		D: serde::Deserializer<'de>,
262	{
263		struct SnowflakeVisitor;
264
265		impl<'de> Visitor<'de> for SnowflakeVisitor {
266			type Value = SnowFlake;
267
268			fn expecting(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
269				f.write_str("Snowflake as a number or string")
270			}
271
272			fn visit_i64<E>(self, id: i64) -> Result<Self::Value, E>
273			where
274				E: de::Error,
275			{
276				Ok(SnowFlake(id))
277			}
278
279			fn visit_u64<E>(self, id: u64) -> Result<Self::Value, E>
280			where
281				E: de::Error,
282			{
283				if id < i64::MAX as u64 {
284					Ok(SnowFlake(id.try_into().unwrap()))
285				} else {
286					Err(E::custom(format!("Snowflake out of range: {}", id)))
287				}
288			}
289
290			fn visit_str<E>(self, id: &str) -> Result<Self::Value, E>
291			where
292				E: de::Error,
293			{
294				match id.parse::<u64>() {
295					Ok(val) => self.visit_u64(val),
296					Err(_) => Err(E::custom("Failed to parse snowflake")),
297				}
298			}
299		}
300
301		deserializer.deserialize_any(SnowflakeVisitor)
302	}
303}
304
305impl Serialize for SnowFlake {
306	fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
307	where
308		S: Serializer,
309	{
310		// Convert the u64 to a string
311		let s = self.0.to_string();
312
313		// Serialize the string
314		serializer.serialize_str(&s)
315	}
316}
317
318#[test]
319fn test_generate() {
320	let id_generator = NumericalUniqueIdGenerator::new(1, 2);
321	let mut ids = Vec::with_capacity(10000);
322
323	for _ in 0..99 {
324		for _ in 0..10000 {
325			ids.push(id_generator.generate());
326		}
327
328		ids.sort();
329		ids.dedup();
330
331		assert_eq!(10000, ids.len());
332
333		ids.clear();
334	}
335}
336#[test]
337fn test_generate_not_sequential_value_when_sleep() {
338	let id_generator = NumericalUniqueIdGenerator::new(1, 2);
339	let first = id_generator.generate();
340
341	std::thread::sleep(std::time::Duration::from_millis(1));
342	let second = id_generator.generate();
343
344	assert!(first < second);
345	assert_ne!(first + 1, second);
346}
347
348#[test]
349fn test_singleton_generate() {
350	let id_generator = &ID_GENERATOR;
351	let mut ids = Vec::with_capacity(1000000);
352
353	for _ in 0..99 {
354		for _ in 0..1000000 {
355			ids.push(id_generator.generate());
356		}
357
358		assert_eq!(1000000, ids.len());
359		assert!(ids.first().unwrap() < ids.last().unwrap());
360		assert!(ids.get(999998).unwrap() < ids.get(999999).unwrap());
361
362		ids.clear();
363	}
364}