pub struct RateLimiter { /* private fields */ }Expand description
A token bucket rate limiter.
The rate limiter maintains a bucket of tokens. Each operation consumes one token. When tokens are depleted, operations are rejected until the bucket refills.
§Examples
use do_over::{policy::Policy, rate_limit::RateLimiter, error::DoOverError};
use std::time::Duration;
// 10 requests per second
let limiter = RateLimiter::new(10, Duration::from_secs(1));
// 1000 requests per minute
let limiter = RateLimiter::new(1000, Duration::from_secs(60));Implementations§
Source§impl RateLimiter
impl RateLimiter
Sourcepub fn new(capacity: u64, interval: Duration) -> Self
pub fn new(capacity: u64, interval: Duration) -> Self
Create a new rate limiter.
§Arguments
capacity- Number of tokens (requests) allowed per intervalinterval- Duration after which tokens refill
§Examples
use do_over::rate_limit::RateLimiter;
use std::time::Duration;
// Allow 100 requests per second
let limiter = RateLimiter::new(100, Duration::from_secs(1));
// Allow 5 requests per 100ms (burst limiting)
let limiter = RateLimiter::new(5, Duration::from_millis(100));Examples found in repository?
More examples
examples/rate_limiter.rs (line 27)
22async fn burst_example() {
23 println!("📌 Scenario 1: Burst of Requests");
24 println!(" Configuration: capacity=5, interval=1s");
25 println!(" Sending 8 requests in rapid succession...\n");
26
27 let limiter = RateLimiter::new(5, Duration::from_secs(1));
28 let start = Instant::now();
29
30 let mut allowed = 0;
31 let mut rejected = 0;
32
33 for i in 1..=8 {
34 let result: Result<String, DoOverError<String>> = limiter
35 .execute(|| async move { Ok(format!("Request {} processed", i)) })
36 .await;
37
38 let elapsed = start.elapsed().as_millis();
39 match result {
40 Ok(msg) => {
41 println!(" [+{:>4}ms] Request {}: ✅ {}", elapsed, i, msg);
42 allowed += 1;
43 }
44 Err(DoOverError::BulkheadFull) => {
45 println!(" [+{:>4}ms] Request {}: 🚫 Rate limited", elapsed, i);
46 rejected += 1;
47 }
48 Err(e) => println!(" [+{:>4}ms] Request {}: Error - {:?}", elapsed, i, e),
49 }
50 }
51
52 println!("\n Summary:");
53 println!(" - Allowed: {} (capacity was 5)", allowed);
54 println!(" - Rejected: {} (exceeded capacity)", rejected);
55 println!("\n 💡 First 5 requests used the burst capacity, remaining 3 were rate limited");
56}
57
58async fn replenishment_example() {
59 println!("📌 Scenario 2: Token Replenishment");
60 println!(" Configuration: capacity=3, interval=500ms");
61 println!(" Demonstrating token refill after interval...\n");
62
63 let limiter = RateLimiter::new(3, Duration::from_millis(500));
64 let start = Instant::now();
65
66 // Phase 1: Use up all tokens
67 println!(" Phase 1: Using up all 3 tokens");
68 for i in 1..=4 {
69 let result: Result<String, DoOverError<String>> = limiter
70 .execute(|| async move { Ok(format!("Request {}", i)) })
71 .await;
72
73 let elapsed = start.elapsed().as_millis();
74 match result {
75 Ok(_) => println!(" [+{:>4}ms] Request {}: ✅ Token consumed", elapsed, i),
76 Err(DoOverError::BulkheadFull) => {
77 println!(" [+{:>4}ms] Request {}: 🚫 No tokens available", elapsed, i)
78 }
79 Err(e) => println!(" [+{:>4}ms] Request {}: Error - {:?}", elapsed, i, e),
80 }
81 }
82
83 // Phase 2: Wait for tokens to replenish
84 println!("\n Phase 2: Waiting 500ms for token replenishment...");
85 tokio::time::sleep(Duration::from_millis(500)).await;
86 let elapsed = start.elapsed().as_millis();
87 println!(" [+{:>4}ms] → Tokens should be replenished now", elapsed);
88
89 // Phase 3: Try again after replenishment
90 println!("\n Phase 3: Sending requests after replenishment");
91 for i in 5..=8 {
92 let result: Result<String, DoOverError<String>> = limiter
93 .execute(|| async move { Ok(format!("Request {}", i)) })
94 .await;
95
96 let elapsed = start.elapsed().as_millis();
97 match result {
98 Ok(_) => println!(" [+{:>4}ms] Request {}: ✅ Token consumed", elapsed, i),
99 Err(DoOverError::BulkheadFull) => {
100 println!(" [+{:>4}ms] Request {}: 🚫 No tokens available", elapsed, i)
101 }
102 Err(e) => println!(" [+{:>4}ms] Request {}: Error - {:?}", elapsed, i, e),
103 }
104 }
105
106 println!(
107 "\n 💡 After 500ms, all 3 tokens were replenished and available for use"
108 );
109}Trait Implementations§
Source§impl Clone for RateLimiter
impl Clone for RateLimiter
Source§impl<E> Policy<DoOverError<E>> for RateLimiter
impl<E> Policy<DoOverError<E>> for RateLimiter
Auto Trait Implementations§
impl Freeze for RateLimiter
impl !RefUnwindSafe for RateLimiter
impl Send for RateLimiter
impl Sync for RateLimiter
impl Unpin for RateLimiter
impl !UnwindSafe for RateLimiter
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more