6 releases (3 breaking)
0.4.1 | Nov 10, 2024 |
---|---|
0.4.0 | May 8, 2022 |
0.3.0 | May 6, 2022 |
0.2.1 | Feb 20, 2017 |
0.1.0 | Feb 16, 2017 |
#351 in Encoding
116 downloads per month
26KB
496 lines
frostflake
Customizable and thread-safe distributed id generator, like twitter's snowflake.
Simple usage for single generator
use frostflake::{Generator, GeneratorOptions};
let mut generator = Generator::new(GeneratorOptions::default());
let id1 = generator.generate();
let id2 = generator.generate();
let id3 = generator.generate();
Async generator works with tokio
This requires tokio
feature.
use frostflake::{GeneratorAsync, GeneratorOptions};
#[tokio::main]
async fn main() {
let generator = GeneratorAsync::spawn(GeneratorOptions::default());
let id1 = generator.generate().await.unwrap();
}
GeneratorAsync
is Send
so that you can pass it to other threads or tasks safely.
use frostflake::{GeneratorAsync, GeneratorOptions};
#[tokio::main]
async fn main() {
let g = GeneratorAsync::spawn(GeneratorOptions::default());
for _ in 0..10 {
let g = g.clone();
tokio::spawn(async move {
let id = g.generate().await.unwrap();
});
}
}
Multi-threads generator by GeneratorPool
This requires std-thread
feature.
use frostflake::{GeneratorPool, GeneratorPoolOptions};
use std::thread;
// create 10 generators
let pool = GeneratorPool::new(10, GeneratorPoolOptions::default());
{
// pool also can be shared with threads by std::sync::Arc
let pool = pool.clone();
thread::spawn(move || {
let id = pool.generate();
}).join();
}
Configurations
frostflake is highly configurable.
use frostflake::{Generator, GeneratorOptions};
let opts = GeneratorOptions::default()
.bits(42, 10, 12) // 42bit timestamp, 10bit node, 12bit sequence
.base_ts(1483228800000) // base time 2017-01-01T00:00:00Z as milliseonds
.node(3); // node number
let generator = Generator::new(opts);
Also, time function is can be set. If you want to use plain seconds unit instead of millisedond, you can do by this:
use frostflake::{Generator, GeneratorOptions};
use std::time::{SystemTime, UNIX_EPOCH};
fn my_time() -> u64 {
let t = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
t.as_secs()
}
// use smaller time bits (because this is not milliseconds)
// use larger sequence bits
let opts = GeneratorOptions::default()
.base_ts(0) // need this for avoid exceeding time value on smaller bit size
.bits(36, 10, 18)
.base_ts(1483228800) // base time should be second too
.time_fn(my_time); // set my time function
let generator = Generator::new(opts);
Default configurations
Generator
Options | Default value |
---|---|
bits | 42=timestamp, 10=node, 12=sequence |
base_ts | 1483228800000 (2017-01-01T00:00:00Z as milliseonds) |
node | 0 |
time_fn | return current milliseonds |
GeneratorPool
Almost same as Generator, but GeneratorPool uses pool_id
bit for distinguish each pools.
So default bit widths is:
Options | Default value |
---|---|
bits | 42=timestamp, 4=pool_id, 6=node, 12=sequence |
All other options are same with Generator.
TODO
- Support redis based automatic node_id generation like katsubushi
- Support other async runtimes?
Patches or pull-requests are always welcome.
Dependencies
~0–5.5MB
~20K SLoC