snowflake_me/
lib.rs

1// Copyright 2022 houseme
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6// option. This file may not be copied, modified, or distributed
7// except according to those terms.
8
9//! A high-performance, highly concurrent, distributed Snowflake ID generator.
10//!
11//! This implementation is **lock-free**, designed for maximum throughput and minimum latency on multi-core CPUs.
12//!
13//! ## Highlights
14//!
15//! - **Lock-Free Concurrency**: Uses `AtomicU64` and CAS operations to manage internal state, eliminating `Mutex` lock overhead.
16//! - **High Performance**: The lock-free design makes ID generation extremely fast, performing exceptionally well under high concurrency.
17//! - **Highly Customizable**: The `Builder` pattern allows you to flexibly configure the start time, machine ID, data center ID, and the bit lengths of each component.
18//! - **Smart IP Fallback**: With the `ip-fallback` feature enabled, if `machine_id` or `data_center_id` are not provided, the system automatically derives them from local network interfaces.
19//!     - **Supports both IPv4 and IPv6**: It prioritizes private IPv4 addresses and falls back to private IPv6 addresses.
20//!     - **Conflict-Free**: To ensure uniqueness, `machine_id` and `data_center_id` are derived from distinct parts of the IP address.
21//!
22//! ## Quick Start
23//!
24//! ### 1. Add Dependency
25//!
26//! Add this to your `Cargo.toml`. To use automatic IP-based configuration, enable the `ip-fallback` feature.
27//!
28//! ```toml
29//! [dependencies]
30//! snowflake-me = { version = "0.4.0", features = ["ip-fallback"] }
31//! ```
32//!
33//! ### 2. Basic Usage
34//!
35//! ```rust
36//! use snowflake_me::Snowflake;
37//!
38//! // Create a generator with the default configuration.
39//! // Note: This requires the `ip-fallback` feature to auto-detect machine and data center IDs.
40//! # #[cfg(feature = "ip-fallback")]
41//! # {
42//! let sf = Snowflake::new().unwrap();
43//! let next_id = sf.next_id().unwrap();
44//! println!("Generated ID: {}", next_id);
45//! # }
46//! ```
47//!
48//! ## Recommended Usage for Production
49//!
50//! For production environments, it is highly recommended to use the `Builder` to manually configure `machine_id` and `data_center_id` for maximum reliability.
51//!
52//! ```rust
53//! use snowflake_me::Snowflake;
54//! use std::thread;
55//! use std::sync::Arc;
56//! use std::collections::HashSet;
57//!
58//! // Manually configure IDs for reliability.
59//! let sf = Snowflake::builder()
60//!     .machine_id(&|| Ok(10))
61//!     .data_center_id(&|| Ok(5))
62//!     .finalize()
63//!     .unwrap();
64//!
65//! let sf_arc = Arc::new(sf);
66//! let mut handles = vec![];
67//!
68//! for _ in 0..10 {
69//!     let sf_clone = Arc::clone(&sf_arc);
70//!     let handle = thread::spawn(move || {
71//!         let mut ids = Vec::new();
72//!         for _ in 0..1000 {
73//!             ids.push(sf_clone.next_id().unwrap());
74//!         }
75//!         ids
76//!     });
77//!     handles.push(handle);
78//! }
79//!
80//! let mut all_ids = HashSet::new();
81//! for handle in handles {
82//!     let ids = handle.join().unwrap();
83//!     for id in ids {
84//!         // Verify that all IDs are unique
85//!         assert!(all_ids.insert(id), "Found duplicate ID: {}", id);
86//!     }
87//! }
88//!
89//! println!("Successfully generated {} unique IDs.", all_ids.len());
90//! ```
91//!
92//! ## Decomposing an ID
93//!
94//! You can decompose a Snowflake ID back into its original components.
95//!
96//! ```rust
97//! use snowflake_me::{Snowflake, DecomposedSnowflake};
98//!
99//! // Use the same configuration that was used for generation.
100//! let sf = Snowflake::builder()
101//!     .machine_id(&|| Ok(15))
102//!     .data_center_id(&|| Ok(7))
103//!     .finalize()
104//!     .unwrap();
105//!
106//! let id = sf.next_id().unwrap();
107//!
108//! // Decompose the ID using the generator's configuration.
109//! let decomposed = sf.decompose(id);
110//!
111//! println!("ID: {}", decomposed.id);
112//! println!("Time: {}", decomposed.time);
113//! println!("Data Center ID: {}", decomposed.data_center_id);
114//! println!("Machine ID: {}", decomposed.machine_id);
115//! println!("Sequence: {}", decomposed.sequence);
116//!
117//! assert_eq!(decomposed.machine_id, 15);
118//! assert_eq!(decomposed.data_center_id, 7);
119//! ```
120//!
121//! [Twitter's Snowflake]: https://blog.twitter.com/2010/announcing-snowflake
122
123#![doc(html_root_url = "https://docs.rs/snowflake-me/*")]
124
125#[cfg(doctest)]
126#[doc = include_str!("../README.md")]
127pub struct ReadmeDoctests;
128
129mod builder;
130mod error;
131mod snowflake;
132
133#[cfg(test)]
134mod tests;
135
136pub use builder::Builder;
137pub use error::Error;
138pub use snowflake::{DecomposedSnowflake, Snowflake};