Files
zesdex/crates/zesdex-backend/src/app/util/backoff.rs
T
asepharyana ab1a54b72e Refactor error handling in IAM and CMS crates
- Introduced `RepositoryError` and `ServiceError` enums in both IAM and CMS domains for better error management.
- Updated domain traits and services to return specific error types instead of `anyhow::Result`.
- Enhanced session and OAuth repository implementations to handle errors more explicitly.
- Refactored session service methods to return `Result<T, ServiceError>` for improved error handling.
- Updated HTTP handlers to utilize the new error types.
- Modified password hashing functions to run in a blocking context using `tokio::task::spawn_blocking`.
- Added tests for new error handling mechanisms and async password functions.
2026-07-20 06:14:23 +07:00

37 lines
1.4 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//! Exponential backoff with jitter.
//!
//! Three use cases (subagent, provider, workflow) all share the same formula
//! with different caps. This module provides a single implementation.
use std::convert::TryInto;
use std::time::{Duration, SystemTime, UNIX_EPOCH};
/// Compute an exponential backoff with ±25% jitter.
///
/// `attempt` is 0-based (first retry -> attempt=0 -> base=1s,
/// second retry -> attempt=1 -> base=2s, etc.).
/// `max_secs` sets the cap.
pub fn backoff_seconds(attempt: u32, max_secs: u64) -> Duration {
let base_secs = (2u64).pow(attempt).min(max_secs);
// 25% of base (in nanoseconds), floored at 100ms so very low
// attempts still have meaningful jitter.
let quarter = (base_secs * 250_000_000).max(100_000_000);
let offset = jitter_ns(quarter * 2); // [0, 50% of base)
// ±25%: offset in [0, 2×quarter), result = base + offset - quarter
// which lies in [base - 25%, base + 25%).
let ns = base_secs * 1_000_000_000 + offset - quarter;
Duration::from_nanos(ns)
}
/// Return a jitter offset in the range [0, range_ns).
///
/// Uses sub-nanosecond wall-clock bits as a cheap PRNG source — no
/// need for a full RNG for ±25% backoff jitter.
fn jitter_ns(range_ns: u64) -> u64 {
let dur = SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap_or_default();
let nanos: u64 = dur.as_nanos().try_into().unwrap_or(u64::MAX);
nanos % range_ns
}