diff --git a/src/builder.rs b/src/builder.rs index 3094e76..7a33a03 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -66,9 +66,9 @@ impl<'a> Builder<'a> { return Err(Error::StartTimeAheadOfCurrentTime(start_time)); } - to_sonyflake_time(start_time) + to_sonyflake_time(start_time)? } else { - to_sonyflake_time(Utc.with_ymd_and_hms(2014, 9, 1, 0, 0, 0).unwrap()) + to_sonyflake_time(Utc.with_ymd_and_hms(2014, 9, 1, 0, 0, 0).unwrap())? }; let machine_id = if let Some(machine_id) = self.machine_id { diff --git a/src/error.rs b/src/error.rs index e5d2e52..10bbf05 100644 --- a/src/error.rs +++ b/src/error.rs @@ -20,4 +20,6 @@ pub enum Error { NoPrivateIPv4, #[error("mutex is poisoned (i.e. a panic happened while it was locked)")] MutexPoisoned, + #[error("failed to get current time")] + FailedToGetCurrentTime, } diff --git a/src/sonyflake.rs b/src/sonyflake.rs index df61c91..178cc29 100644 --- a/src/sonyflake.rs +++ b/src/sonyflake.rs @@ -56,7 +56,7 @@ impl Sonyflake { pub fn next_id(&self) -> Result { let mut internals = self.0.internals.lock().map_err(|_| Error::MutexPoisoned)?; - let current = current_elapsed_time(self.0.start_time); + let current = current_elapsed_time(self.0.start_time)?; if internals.elapsed_time < current { internals.elapsed_time = current; internals.sequence = 0; @@ -66,7 +66,7 @@ impl Sonyflake { if internals.sequence == 0 { internals.elapsed_time += 1; let overtime = internals.elapsed_time - current; - thread::sleep(sleep_time(overtime)); + thread::sleep(sleep_time(overtime)?); } } @@ -91,17 +91,25 @@ impl Clone for Sonyflake { const SONYFLAKE_TIME_UNIT: i64 = 10_000_000; // nanoseconds, i.e. 10msec -pub(crate) fn to_sonyflake_time(time: DateTime) -> i64 { - time.timestamp_nanos() / SONYFLAKE_TIME_UNIT +pub(crate) fn to_sonyflake_time(time: DateTime) -> Result { + Ok(time + .timestamp_nanos_opt() + .ok_or(Error::FailedToGetCurrentTime)? + / SONYFLAKE_TIME_UNIT) } -fn current_elapsed_time(start_time: i64) -> i64 { - to_sonyflake_time(Utc::now()) - start_time +fn current_elapsed_time(start_time: i64) -> Result { + Ok(to_sonyflake_time(Utc::now())? - start_time) } -fn sleep_time(overtime: i64) -> Duration { - Duration::from_millis(overtime as u64 * 10) - - Duration::from_nanos((Utc::now().timestamp_nanos() % SONYFLAKE_TIME_UNIT) as u64) +fn sleep_time(overtime: i64) -> Result { + Ok(Duration::from_millis(overtime as u64 * 10) + - Duration::from_nanos( + (Utc::now() + .timestamp_nanos_opt() + .ok_or(Error::FailedToGetCurrentTime)? + % SONYFLAKE_TIME_UNIT) as u64, + )) } pub struct DecomposedSonyflake { diff --git a/src/tests.rs b/src/tests.rs index 280de25..3ed9f51 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -52,7 +52,7 @@ fn test_once() -> Result<(), BoxDynError> { #[test] fn test_run_for_10s() -> Result<(), BoxDynError> { let now = Utc::now(); - let start_time = to_sonyflake_time(now); + let start_time = to_sonyflake_time(now)?; let sf = Sonyflake::builder().start_time(now).finalize()?; let mut last_id: u64 = 0; @@ -60,7 +60,7 @@ fn test_run_for_10s() -> Result<(), BoxDynError> { let machine_id = lower_16_bit_private_ip()? as u64; - let initial = to_sonyflake_time(Utc::now()); + let initial = to_sonyflake_time(Utc::now())?; let mut current = initial.clone(); while current - initial < 1000 { let id = sf.next_id()?; @@ -71,7 +71,7 @@ fn test_run_for_10s() -> Result<(), BoxDynError> { } last_id = id; - current = to_sonyflake_time(Utc::now()); + current = to_sonyflake_time(Utc::now())?; let actual_msb = parts.msb; if actual_msb != 0 {