clamber_core/snowflake/
mod.rs1use crate::error::{ClamberError, Result};
2use serde::{Deserialize, Serialize};
3use std::sync::Mutex;
4use twitter_snowflake::Snowflake;
5
6#[derive(Debug, Clone, Serialize, Deserialize)]
8pub struct SnowflakeConfig {
9 pub worker_id: u64,
11 pub epoch: Option<u64>,
13}
14
15impl Default for SnowflakeConfig {
16 fn default() -> Self {
17 Self {
18 worker_id: 1,
19 epoch: None, }
21 }
22}
23
24impl SnowflakeConfig {
25 pub fn new(worker_id: u64) -> Result<Self> {
27 Self::validate_worker_id(worker_id)?;
28
29 Ok(Self {
30 worker_id,
31 epoch: None,
32 })
33 }
34
35 pub fn with_epoch(worker_id: u64, epoch: u64) -> Result<Self> {
37 Self::validate_worker_id(worker_id)?;
38
39 Ok(Self {
40 worker_id,
41 epoch: Some(epoch),
42 })
43 }
44
45 pub fn worker_id(mut self, worker_id: u64) -> Result<Self> {
47 Self::validate_worker_id(worker_id)?;
48 self.worker_id = worker_id;
49 Ok(self)
50 }
51
52 pub fn epoch(mut self, epoch: u64) -> Self {
54 self.epoch = Some(epoch);
55 self
56 }
57
58 fn validate_worker_id(worker_id: u64) -> Result<()> {
60 if worker_id > 1023 {
61 return Err(ClamberError::SnowflakeConfigError {
62 details: format!("工作者ID必须在0-1023范围内,当前值: {}", worker_id),
63 });
64 }
65 Ok(())
66 }
67}
68
69pub struct SnowflakeManager {
71 generator: Mutex<Snowflake>,
72 config: SnowflakeConfig,
73}
74
75impl SnowflakeManager {
76 pub fn new(config: SnowflakeConfig) -> Result<Self> {
78 let generator = if let Some(epoch) = config.epoch {
79 Snowflake::builder()
80 .with_worker_id(config.worker_id)
81 .with_epoch(epoch)
82 .build()
83 } else {
84 Snowflake::new(config.worker_id)
85 };
86
87 let generator = generator.map_err(|e| ClamberError::SnowflakeInitError {
88 details: format!("初始化Snowflake生成器失败: {:?}", e),
89 })?;
90
91 Ok(Self {
92 generator: Mutex::new(generator),
93 config,
94 })
95 }
96
97 pub fn default() -> Result<Self> {
99 Self::new(SnowflakeConfig::default())
100 }
101
102 pub fn generate_id(&self) -> Result<u64> {
104 let mut generator =
105 self.generator
106 .lock()
107 .map_err(|e| ClamberError::SnowflakeGenerateError {
108 details: format!("获取生成器锁失败: {}", e),
109 })?;
110
111 generator
112 .generate()
113 .map_err(|e| ClamberError::SnowflakeGenerateError {
114 details: format!("生成ID失败: {:?}", e),
115 })
116 }
117
118 pub fn generate_ids(&self, count: usize) -> Result<Vec<u64>> {
120 let mut ids = Vec::with_capacity(count);
121 for _ in 0..count {
122 ids.push(self.generate_id()?);
123 }
124 Ok(ids)
125 }
126
127 pub fn get_config(&self) -> &SnowflakeConfig {
129 &self.config
130 }
131
132 pub fn worker_id(&self) -> u64 {
134 self.config.worker_id
135 }
136
137 pub fn parse_id(&self, id: u64) -> SnowflakeIdInfo {
139 let timestamp = (id >> 22) & 0x1FFFFFFFFFF; let worker_id = (id >> 12) & 0x3FF; let sequence = id & 0xFFF; SnowflakeIdInfo {
145 id,
146 timestamp,
147 worker_id,
148 sequence: sequence as u16,
149 }
150 }
151}
152
153#[derive(Debug, Clone, Serialize, Deserialize)]
155pub struct SnowflakeIdInfo {
156 pub id: u64,
158 pub timestamp: u64,
160 pub worker_id: u64,
162 pub sequence: u16,
164}
165
166impl SnowflakeIdInfo {
167 pub fn generation_time(&self, epoch: Option<u64>) -> u64 {
169 let epoch = epoch.unwrap_or(1288834974657); self.timestamp + epoch
171 }
172
173 pub fn generation_time_string(&self, epoch: Option<u64>) -> String {
175 let timestamp_ms = self.generation_time(epoch);
176 let datetime = chrono::DateTime::from_timestamp_millis(timestamp_ms as i64);
177 match datetime {
178 Some(dt) => dt.format("%Y-%m-%d %H:%M:%S%.3f").to_string(),
179 None => "Invalid timestamp".to_string(),
180 }
181 }
182
183 pub fn to_string(&self) -> String {
185 self.id.to_string()
186 }
187
188 pub fn from_string(id_str: &str) -> Result<u64> {
190 id_str
191 .parse::<u64>()
192 .map_err(|e| ClamberError::SnowflakeConfigError {
193 details: format!("无法解析ID字符串: {}", e),
194 })
195 }
196}
197
198use once_cell::sync::Lazy;
200
201static DEFAULT_MANAGER: Lazy<Result<SnowflakeManager>> = Lazy::new(|| SnowflakeManager::default());
202
203fn get_default_manager() -> Result<&'static SnowflakeManager> {
205 match &*DEFAULT_MANAGER {
206 Ok(manager) => Ok(manager),
207 Err(e) => Err(ClamberError::SnowflakeInitError {
208 details: format!("无法初始化默认Snowflake管理器: {}", e),
209 }),
210 }
211}
212
213pub fn generate_id() -> Result<u64> {
215 get_default_manager()?.generate_id()
216}
217
218pub fn generate_ids(count: usize) -> Result<Vec<u64>> {
220 get_default_manager()?.generate_ids(count)
221}
222
223pub fn parse_id(id: u64) -> Result<SnowflakeIdInfo> {
225 Ok(get_default_manager()?.parse_id(id))
226}
227
228pub fn generate_string_id() -> Result<String> {
230 Ok(generate_id()?.to_string())
231}
232
233pub fn parse_string_id(id_str: &str) -> Result<SnowflakeIdInfo> {
235 let id = SnowflakeIdInfo::from_string(id_str)?;
236 parse_id(id)
237}
238
239#[cfg(test)]
240mod tests {
241 use super::*;
242 use std::collections::HashSet;
243
244 #[test]
245 fn test_snowflake_config_creation() {
246 let config = SnowflakeConfig::new(1).unwrap();
248 assert_eq!(config.worker_id, 1);
249 assert!(config.epoch.is_none());
250
251 let config_with_epoch = SnowflakeConfig::with_epoch(3, 1609459200000).unwrap();
253 assert_eq!(config_with_epoch.worker_id, 3);
254 assert_eq!(config_with_epoch.epoch, Some(1609459200000));
255
256 assert!(SnowflakeConfig::new(1024).is_err());
258 }
259
260 #[test]
261 fn test_snowflake_manager_creation() {
262 let config = SnowflakeConfig::new(1).unwrap();
263 let manager = SnowflakeManager::new(config).unwrap();
264 assert_eq!(manager.worker_id(), 1);
265 }
266
267 #[test]
268 fn test_id_generation() {
269 let config = SnowflakeConfig::new(1).unwrap();
270 let manager = SnowflakeManager::new(config).unwrap();
271
272 let id = manager.generate_id().unwrap();
274 assert!(id > 0);
275
276 let ids = manager.generate_ids(100).unwrap();
278 assert_eq!(ids.len(), 100);
279
280 let unique_ids: HashSet<u64> = ids.into_iter().collect();
281 assert_eq!(unique_ids.len(), 100); }
283
284 #[test]
285 fn test_id_parsing() {
286 let config = SnowflakeConfig::new(1).unwrap();
287 let manager = SnowflakeManager::new(config).unwrap();
288
289 let id = manager.generate_id().unwrap();
290 let info = manager.parse_id(id);
291
292 assert_eq!(info.id, id);
293 assert!(info.timestamp > 0);
294 }
295
296 #[test]
297 fn test_convenience_functions() {
298 let id = generate_id().unwrap();
300 assert!(id > 0);
301
302 let ids = generate_ids(10).unwrap();
303 assert_eq!(ids.len(), 10);
304
305 let info = parse_id(id).unwrap();
306 assert_eq!(info.id, id);
307 }
308
309 #[test]
310 fn test_string_functions() {
311 let id = generate_string_id().unwrap();
312 assert!(!id.is_empty());
313
314 let info = parse_string_id(&id).unwrap();
315 assert_eq!(info.to_string(), id);
316 }
317
318 #[test]
319 fn test_id_info_time_functions() {
320 let id = generate_id().unwrap();
321 let info = parse_id(id).unwrap();
322
323 let gen_time = info.generation_time(None);
324 assert!(gen_time > 0);
325
326 let time_str = info.generation_time_string(None);
327 assert!(!time_str.is_empty());
328 assert!(time_str.contains("-")); }
330}