6 releases

0.1.5 Oct 30, 2024
0.1.4 Oct 25, 2024

#335 in Data structures

Download history 288/week @ 2024-10-21 172/week @ 2024-10-28 234/week @ 2024-11-04 29/week @ 2024-11-11

723 downloads per month

MIT/Apache

23KB
333 lines

snowflake-ng

GitHub Actions Workflow Status Crates.io Version

Dead easy and high performance snowflake implemented in Rust.

This crate only implemented Twitter(formally X)'s snowflake.

Why ng or next-generation?

Actually, this crate doesn't next-generation enough.

The use of -ng is simply to distinguish between the two existing implementations:

Maybe lock-free can be a feature of next-generation :)

Whats the different between them?

  • The snowflake crate is completely unmaintained and it's even using Rust 2018 Edition.
  • The snowflake-rs (rs-snowflake at crates.io) doesn't support async/await.

Why we need async?

What we need to know is that only 4096 Snowflake ID can be generated in a millisecond in the standard implementation.

If we assigned out the sequence(from 0 to 4095), we have to waiting for one millisecond. If we doesn't use the asynchronous, we have to sleep for one millisecond!

But at the same time, this crate also provided synchronous function, but you have to enable sync feature:

snowflake-ng = { version = "0.1", features = ["sync"]}

Thread safety?

YES!

Inner data use Atomic* type to keep lock-free and atomic update.

So you can share SnowflakeGenerator between threads safety, or make a global static one!

How to use?

Firstly, add this crate to your Cargo.toml:

snowflake-ng = "0.1"

This crate provide some extra TimeProvider implementation based different crate:

  • time
  • chrono

And provide basic implementation based standard library: std::time::SystemTime

If you want to accelerate your build time, you can disable all the features to avoid introduce extra build dependencies.

After add to Cargo.toml, you can made your own SnowflakeGenerator:

let generator = SnowflakeGenerator::default();

Then, start your generation:

generator.assign_sync(&STD_PROVIDER)

You can wrap your own SnowflakeGenerator (I called PersistedSnowflakeGenerator):

let generator = PersistedSnowflakeGenerator::new(Arc::new(SnowflakeGenerator::default()), Arc::new(StdProvider));
generator.assign().await

Please see example for more example such as async support and custom identifier.

Dependencies

~2.8–4MB
~73K SLoC