diff --git a/CHANGELOG.md b/CHANGELOG.md index 93797caf..6fc0e412 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,7 @@ If you are upgrading from v0.16.x, replace the binary (or run `docker pull`). If - Auto-ban: IP block expiration ignores per-reason ban durations. - Meilisearch: Limit the text search scope using `attributesToSearchOn`. - CalDAV: `calendar-query` REPORT returns invalid HTTP `404` when no events match the query. +- Snowflake past id generation fails when the provided duration is longer than 4 years. ## [0.16.11] - 2026-06-25 diff --git a/crates/utils/src/snowflake.rs b/crates/utils/src/snowflake.rs index 6fb63534..84638619 100644 --- a/crates/utils/src/snowflake.rs +++ b/crates/utils/src/snowflake.rs @@ -63,8 +63,9 @@ impl SnowflakeIdGenerator { (SystemTime::UNIX_EPOCH + Duration::from_secs(DEFAULT_EPOCH)) .elapsed() .ok() - .and_then(|elapsed| elapsed.checked_sub(period)) - .map(|elapsed| (elapsed.as_millis() as u64) << (SEQUENCE_LEN + NODE_ID_LEN)) + .map(|elapsed| { + (elapsed.saturating_sub(period).as_millis() as u64) << (SEQUENCE_LEN + NODE_ID_LEN) + }) } pub fn from_timestamp(timestamp: u64) -> Option { @@ -99,11 +100,9 @@ impl SnowflakeIdGenerator { #[inline(always)] pub fn past_id(&self, period: Duration) -> Option { - self.epoch - .elapsed() - .ok() - .and_then(|elapsed| elapsed.checked_sub(period)) - .map(|elapsed| (elapsed.as_millis() as u64) << (SEQUENCE_LEN + NODE_ID_LEN)) + self.epoch.elapsed().ok().map(|elapsed| { + (elapsed.saturating_sub(period).as_millis() as u64) << (SEQUENCE_LEN + NODE_ID_LEN) + }) } pub fn is_valid(&self) -> bool {