rust 47 lines · 8 steps

A token bucket rate limiter in Rust

A token bucket refills tokens over time and only allows work when enough tokens are on hand.

Explained by highlit
1use std::time::{Duration, Instant};
2 
3pub struct TokenBucket {
4 capacity: f64,
5 tokens: f64,
6 refill_per_sec: f64,
7 last_refill: Instant,
8}
9 
10impl TokenBucket {
11 pub fn new(capacity: f64, refill_per_sec: f64) -> Self {
12 Self {
13 capacity,
14 tokens: capacity,
15 refill_per_sec,
16 last_refill: Instant::now(),
17 }
18 }
19 
20 fn refill(&mut self) {
21 let now = Instant::now();
22 let elapsed = now.duration_since(self.last_refill).as_secs_f64();
23 if elapsed > 0.0 {
24 self.tokens = (self.tokens + elapsed * self.refill_per_sec).min(self.capacity);
25 self.last_refill = now;
26 }
27 }
28 
29 pub fn try_acquire(&mut self, cost: f64) -> bool {
30 self.refill();
31 if self.tokens >= cost {
32 self.tokens -= cost;
33 true
34 } else {
35 false
36 }
37 }
38 
39 pub fn time_until_available(&mut self, cost: f64) -> Duration {
40 self.refill();
41 if self.tokens >= cost {
42 return Duration::ZERO;
43 }
44 let deficit = cost - self.tokens;
45 Duration::from_secs_f64(deficit / self.refill_per_sec)
46 }
47}
01 / 01
STEP 01

Walkthrough

Space play step click any line
Three takeaways
  1. 1Lazy refill on each access avoids background timers by computing tokens from elapsed time.
  2. 2Clamping to capacity keeps a bucket from accumulating credit while idle.
  3. 3Storing the last refill instant lets you derive both availability and wait time from one clock read.

Related explainers

Share this explainer

Here's the card — post it anywhere.

A token bucket rate limiter in Rust — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code