fix: no more id collisions

This commit is contained in:
trisua 2025-05-06 16:13:48 -04:00
parent 71d017693c
commit 0b3573a513
11 changed files with 151 additions and 120 deletions

View file

@ -11,8 +11,8 @@ ammonia = "4.1.0"
chrono = "0.4.41"
comrak = "0.38.0"
hex_fmt = "0.3.0"
num-bigint = "0.4.6"
rand = "0.9.1"
serde = "1.0.219"
sha2 = "0.10.8"
snowflaked = "1.0.3"
uuid = { version = "1.16.0", features = ["v4"] }

View file

@ -1,51 +1,29 @@
//! Almost Snowflake
//!
//! Random IDs which include timestamp information (like Twitter Snowflakes)
//!
//! IDs are generated with 41 bits of an epoch timestamp, 10 bits of a machine/server ID, and 12 bits of randomly generated numbers.
//!
//! ```
//! tttttttttttttttttttttttttttttttttttttttttiiiiiiiiiirrrrrrrrrrrr...
//! Timestamp ID Seed
//! ```
use crate::epoch_timestamp;
use std::time::{UNIX_EPOCH, Duration};
use serde::{Deserialize, Serialize};
use snowflaked::{Builder, Generator};
use num_bigint::BigInt;
use rand::Rng;
static SEED_LEN: usize = 12;
// static ID_LEN: usize = 10;
pub const EPOCH_2024: u64 = 1704067200000;
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct AlmostSnowflake(String);
pub struct Snowflake(String);
pub fn bigint(input: usize) -> BigInt {
BigInt::from(input)
}
impl Snowflake {
pub fn builder() -> Builder {
Builder::new().epoch(UNIX_EPOCH + Duration::from_millis(EPOCH_2024))
}
impl AlmostSnowflake {
/// Create a new [`AlmostSnowflake`]
pub fn new(server_id: usize) -> Self {
// generate random bytes
let mut bytes = String::new();
let mut rng = rand::rng();
for _ in 1..=SEED_LEN {
bytes.push_str(&rng.random_range(0..10).to_string())
}
// build id
let mut id = bigint(epoch_timestamp(2024) as usize) << 22_u128;
id |= bigint((server_id % 1024) << 12);
id |= bigint((bytes.parse::<usize>().unwrap() + 1) % 4096);
// return
Self(id.to_string())
pub fn new() -> Self {
Self(
Self::builder()
.build::<Generator>()
.generate::<u64>()
.to_string(),
)
}
}
impl std::fmt::Display for AlmostSnowflake {
impl std::fmt::Display for Snowflake {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.0)
}