AirLibrary/Downloader/
RateLimit.rs1#![allow(unused_variables, dead_code, unused_imports)]
2
3use std::time::{Duration, Instant};
12
13use crate::Result;
14
15#[derive(Debug)]
18pub struct TokenBucket {
19 tokens:f64,
21 capacity:f64,
23 refill_rate:f64,
25 last_refill:Instant,
27}
28
29impl TokenBucket {
30 pub fn new(bytes_per_sec:u64, capacity_factor:f64) -> Self {
33 let refill_rate = bytes_per_sec as f64;
34 let capacity = refill_rate * capacity_factor;
35 Self { tokens:capacity, capacity, refill_rate, last_refill:Instant::now() }
36 }
37
38 pub fn refill(&mut self) {
40 let elapsed = self.last_refill.elapsed().as_secs_f64();
41 if elapsed > 0.0 {
42 self.tokens = (self.tokens + elapsed * self.refill_rate).min(self.capacity);
43 self.last_refill = Instant::now();
44 }
45 }
46
47 pub fn try_consume(&mut self, bytes:u64) -> u64 {
51 self.refill();
52 let bytes = bytes as f64;
53 if self.tokens >= bytes {
54 self.tokens -= bytes;
55 bytes as u64
56 } else {
57 let available = self.tokens;
58 self.tokens = 0.0;
59 available as u64
60 }
61 }
62
63 pub async fn consume(&mut self, bytes:u64) -> Result<()> {
66 let bytes_needed = bytes as f64;
67 loop {
68 self.refill();
69 if self.tokens >= bytes_needed {
70 self.tokens -= bytes_needed;
71 return Ok(());
72 }
73 let tokens_needed = bytes_needed - self.tokens;
74 let wait_secs = (tokens_needed / self.refill_rate).min(0.1);
75 tokio::time::sleep(Duration::from_secs_f64(wait_secs)).await;
76 }
77 }
78
79 pub fn set_rate(&mut self, bytes_per_sec:u64) {
81 self.refill_rate = bytes_per_sec as f64;
82 self.capacity = self.refill_rate * 5.0;
83 }
84}