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