rusty_feeder/
limit.rs

1//! Rate limiting utilities for exchange API compliance
2//!
3//! This module provides various rate limiting implementations to ensure
4//! compliance with exchange API rate limits while maximizing throughput.
5
6use quanta::Instant;
7use std::sync::Arc;
8use std::time::Duration;
9use tokio::sync::Mutex;
10use tokio::time::Interval;
11
12/// Optimized rate limiter implementation
13pub mod optimized_rate_limiter;
14pub use optimized_rate_limiter::OptimizedRateLimiter;
15
16/// Lock-free rate limiter for high-performance scenarios
17pub mod lockfree_rate_limiter;
18pub use lockfree_rate_limiter::{LockFreeRateLimiter, TokenGuard};
19
20/// Helper utilities for rate limiting
21pub mod helpers;
22pub use helpers::*;
23
24/// A rate limiter that controls the rate of requests within a time window
25#[derive(Debug)]
26pub struct RateLimiter {
27    /// Interval timer for rate limiting
28    #[allow(dead_code)]
29    interval: Mutex<Interval>,
30    /// Maximum number of requests allowed in the time window
31    max_requests: usize,
32    /// Duration of the time window
33    time_window: Duration,
34    /// Shared state for tracking requests
35    state: Arc<Mutex<RateLimitState>>,
36}
37
38impl Clone for RateLimiter {
39    fn clone(&self) -> Self {
40        Self {
41            interval: Mutex::new(tokio::time::interval(
42                self.time_window / self.max_requests as u32,
43            )),
44            max_requests: self.max_requests,
45            time_window: self.time_window,
46            state: self.state.clone(),
47        }
48    }
49}
50
51/// State for tracking rate limit usage
52#[derive(Debug)]
53pub struct RateLimitState {
54    /// Number of requests made in the current window
55    request_count: usize,
56    /// Start time of the current window
57    window_start: Instant,
58}
59
60impl RateLimiter {
61    /// Create a new RateLimiter. Allows max_requests within time_window duration.
62    #[must_use]
63    pub fn new(max_requests: usize, time_window: Duration) -> Self {
64        Self {
65            interval: Mutex::new(tokio::time::interval(time_window / max_requests as u32)),
66            max_requests,
67            time_window,
68            state: Arc::new(Mutex::new(RateLimitState {
69                request_count: 0,
70                window_start: Instant::now(),
71            })),
72        }
73    }
74
75    /// Wait for the interval to tick and check if rate limit is reached.
76    pub async fn wait(&self) {
77        let mut interval = self.interval.lock().await;
78        interval.tick().await;
79
80        let mut state = self.state.lock().await;
81
82        // Reset count and start time if time window has elapsed
83        if state.window_start.elapsed() > self.time_window {
84            state.request_count = 0;
85            state.window_start = Instant::now();
86        }
87
88        // If we've reached max requests in the time window, wait until window resets
89        if state.request_count >= self.max_requests {
90            let window_end = state.window_start.elapsed() + self.time_window;
91            drop(state); // Release lock before await
92            tokio::time::sleep(window_end).await;
93            state = self.state.lock().await; // Re-acquire lock after await
94            // No need to reset here as it will be reset in the next wait cycle if needed
95        }
96        state.request_count += 1;
97    }
98
99    /// Force lock the rate limiter and wait for the interval to tick
100    pub async fn force_lock(&self) {
101        let mut state = self.state.lock().await;
102        state.request_count = self.max_requests;
103        drop(state); // Release lock after update
104    }
105}