saito_core/core/consensus/peers/
rate_limiter.rs1use crate::core::defs::Timestamp;
2use std::time::Duration;
3
4#[derive(Debug, Clone)]
5pub struct RateLimiter {
6 limit: u64,
8 window: Timestamp, request_count: u64, last_request_time: Timestamp, }
12
13impl RateLimiter {
14 pub fn set_limit(&mut self, limit: u64) {
15 self.limit = limit;
16 }
17
18 pub fn set_window(&mut self, window: Timestamp) {
19 self.window = window;
20 }
21
22 pub fn has_limit_exceeded(&mut self, current_time: Timestamp) -> bool {
23 if current_time.saturating_sub(self.last_request_time) > self.window {
25 self.request_count = 0;
26 self.last_request_time = current_time;
27 }
28 self.request_count >= self.limit
29 }
30 pub fn increase(&mut self) {
31 self.request_count += 1;
32 }
33
34 pub fn builder(count: u64, duration: Duration) -> Self {
35 Self {
36 limit: count,
37 window: duration.as_millis() as Timestamp,
38 request_count: 0,
39 last_request_time: 0,
40 }
41 }
42}
43
44#[cfg(test)]
45mod tests {
46 use super::*;
47
48 #[test]
49 fn default_rate_limiter_test() {
50 let rate_limiter = RateLimiter::builder(10, Duration::from_secs(1));
51
52 assert_eq!(rate_limiter.limit, 10);
53 assert_eq!(rate_limiter.window, 1_000);
54 assert_eq!(rate_limiter.request_count, 0);
55 assert_eq!(rate_limiter.last_request_time, 0);
56 }
57
58 #[test]
59 fn set_limit_test() {
60 let mut rate_limiter = RateLimiter::builder(10, Duration::from_secs(1));
61 rate_limiter.set_limit(5);
62
63 assert_eq!(rate_limiter.limit, 5);
64 }
65
66 #[test]
67 fn set_window_test() {
68 let mut rate_limiter = RateLimiter::builder(10, Duration::from_secs(1));
69 rate_limiter.set_window(120_000); assert_eq!(rate_limiter.window, 120_000);
72 }
73
74 #[test]
75 fn can_make_request_within_limit_test() {
76 let mut rate_limiter = RateLimiter::builder(10, Duration::from_secs(1));
77 let current_time = 10_000;
78 rate_limiter.increase();
79 assert_eq!(rate_limiter.request_count, 1);
80 assert!(!rate_limiter.has_limit_exceeded(current_time));
81 assert_eq!(rate_limiter.request_count, 0);
82 }
83
84 #[test]
85 fn can_make_request_exceeding_limit_test() {
86 let mut rate_limiter = RateLimiter::builder(10, Duration::from_secs(1));
87 let current_time = 10_000;
88 for _ in 0..rate_limiter.limit {
89 rate_limiter.increase();
90 assert!(!rate_limiter.has_limit_exceeded(current_time));
91 }
92 rate_limiter.increase();
93 assert!(rate_limiter.has_limit_exceeded(current_time));
94 assert_eq!(rate_limiter.request_count, rate_limiter.limit);
95 }
96
97 #[test]
98 fn can_make_request_after_window_reset_test() {
99 let mut rate_limiter = RateLimiter::builder(10, Duration::from_secs(1));
100 let current_time = 10_000;
101
102 for _ in 0..rate_limiter.limit {
103 rate_limiter.increase();
104 assert!(!rate_limiter.has_limit_exceeded(current_time));
105 }
106 let new_time = current_time + rate_limiter.window + 1;
107 rate_limiter.increase();
108 assert!(!rate_limiter.has_limit_exceeded(new_time));
109 assert_eq!(rate_limiter.request_count, 0);
110 assert_eq!(rate_limiter.last_request_time, new_time);
111 }
112
113 #[test]
114 fn can_make_request_reset_on_new_time_test() {
115 let mut rate_limiter = RateLimiter::builder(10, Duration::from_secs(1));
116 let initial_time = 10_000;
117
118 for _ in 0..rate_limiter.limit {
119 rate_limiter.increase();
120 assert!(!rate_limiter.has_limit_exceeded(initial_time));
121 }
122
123 let later_time = initial_time + rate_limiter.window + 500;
124 rate_limiter.increase();
125 assert!(!rate_limiter.has_limit_exceeded(later_time));
126 dbg!("{}", &rate_limiter);
127 assert_eq!(rate_limiter.request_count, 0);
128 assert_eq!(rate_limiter.last_request_time, later_time);
129 }
130}