Network System 0.1.1
High-performance modular networking library for scalable client-server applications
Loading...
Searching...
No Matches
kcenon::network::rate_limiter Class Reference

Token bucket rate limiter. More...

#include <rate_limiter.h>

Collaboration diagram for kcenon::network::rate_limiter:
Collaboration graph

Classes

struct  bucket
 

Public Member Functions

 rate_limiter (rate_limiter_config config={})
 Construct rate limiter with configuration.
 
bool allow (std::string_view client_id)
 Check if request should be allowed.
 
bool allow (std::string_view client_id, std::string_view session_id)
 Check if request should be allowed (session-aware)
 
bool would_allow (std::string_view client_id) const
 Check if request would be allowed (without consuming token)
 
double remaining_tokens (std::string_view client_id) const
 Get remaining tokens for a client.
 
void reset (std::string_view client_id)
 Reset rate limit for a specific client.
 
void reset_all ()
 Reset all rate limits.
 
size_t client_count () const
 Get number of tracked clients.
 
void set_config (rate_limiter_config config)
 Update configuration.
 
rate_limiter_config config () const
 Get current configuration.
 

Private Member Functions

void maybe_cleanup (std::chrono::steady_clock::time_point now)
 

Private Attributes

rate_limiter_config config_
 
std::shared_mutex mutex_
 
std::unordered_map< std::string, bucketbuckets_
 
std::chrono::steady_clock::time_point last_cleanup_
 

Detailed Description

Token bucket rate limiter.

Implements a token bucket algorithm for rate limiting. Each client is identified by a string key (typically IP address).

Thread Safety

This class is thread-safe. All public methods can be called from multiple threads concurrently.

Algorithm

  • Each client has a bucket with capacity = burst_size
  • Tokens are added at rate = max_requests_per_second
  • Each request consumes one token
  • If no tokens available, request is denied

Definition at line 82 of file rate_limiter.h.

Constructor & Destructor Documentation

◆ rate_limiter()

kcenon::network::rate_limiter::rate_limiter ( rate_limiter_config config = {})
inlineexplicit

Construct rate limiter with configuration.

Parameters
configRate limiter configuration
Examples
/home/runner/work/network_system/network_system/src/internal/utils/rate_limiter.h.

Definition at line 88 of file rate_limiter.h.

88 {})
89 : config_(std::move(config))
90 , last_cleanup_(std::chrono::steady_clock::now()) {}
rate_limiter_config config() const
Get current configuration.
rate_limiter_config config_
std::chrono::steady_clock::time_point last_cleanup_

Member Function Documentation

◆ allow() [1/2]

bool kcenon::network::rate_limiter::allow ( std::string_view client_id)
inlinenodiscard

Check if request should be allowed.

Parameters
client_idClient identifier (e.g., IP address)
Returns
true if request is allowed, false if rate limited
Examples
/home/runner/work/network_system/network_system/src/internal/utils/rate_limiter.h.

Definition at line 98 of file rate_limiter.h.

98 {
99 std::unique_lock<std::shared_mutex> lock(mutex_);
100
101 auto now = std::chrono::steady_clock::now();
102
103 // Periodic cleanup
104 if (config_.auto_cleanup) {
105 maybe_cleanup(now);
106 }
107
108 std::string key(client_id);
109 auto& bucket = buckets_[key];
110
111 // Initialize new bucket
112 if (bucket.last_refill.time_since_epoch().count() == 0) {
113 bucket.tokens = static_cast<double>(config_.burst_size);
114 bucket.last_refill = now;
115 }
116
117 // Refill tokens based on elapsed time
118 auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(
119 now - bucket.last_refill);
120
121 double tokens_to_add = elapsed.count() *
122 (static_cast<double>(config_.max_requests_per_second) / 1000.0);
123
124 bucket.tokens = std::min(
125 static_cast<double>(config_.burst_size),
126 bucket.tokens + tokens_to_add);
127 bucket.last_refill = now;
128
129 // Try to consume a token
130 if (bucket.tokens >= 1.0) {
131 bucket.tokens -= 1.0;
132 return true;
133 }
134
135 return false;
136 }
void maybe_cleanup(std::chrono::steady_clock::time_point now)
std::unordered_map< std::string, bucket > buckets_
size_t burst_size
Maximum burst size (token bucket capacity)
size_t max_requests_per_second
Maximum requests per second.
bool auto_cleanup
Enable automatic cleanup of stale entries.

References kcenon::network::rate_limiter_config::auto_cleanup, buckets_, kcenon::network::rate_limiter_config::burst_size, config_, kcenon::network::rate_limiter::bucket::last_refill, kcenon::network::rate_limiter_config::max_requests_per_second, maybe_cleanup(), mutex_, and kcenon::network::rate_limiter::bucket::tokens.

Referenced by allow().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ allow() [2/2]

bool kcenon::network::rate_limiter::allow ( std::string_view client_id,
std::string_view session_id )
inlinenodiscard

Check if request should be allowed (session-aware)

Parameters
client_idClient identifier (e.g., IP address)
session_idSession identifier for per-session rate limiting
Returns
true if request is allowed, false if rate limited

When session_id is non-empty, a composite key "client_id:session_id" is used, enabling per-session rate limiting. When session_id is empty, falls back to client_id-only behavior.

Definition at line 149 of file rate_limiter.h.

149 {
150 if (session_id.empty()) {
151 return allow(client_id);
152 }
153 std::string composite_key;
154 composite_key.reserve(client_id.size() + 1 + session_id.size());
155 composite_key.append(client_id);
156 composite_key.push_back(':');
157 composite_key.append(session_id);
158 return allow(std::string_view(composite_key));
159 }
bool allow(std::string_view client_id)
Check if request should be allowed.

References allow().

Here is the call graph for this function:

◆ client_count()

size_t kcenon::network::rate_limiter::client_count ( ) const
inlinenodiscard

Get number of tracked clients.

Returns
Number of clients in rate limiter
Examples
/home/runner/work/network_system/network_system/src/internal/utils/rate_limiter.h.

Definition at line 236 of file rate_limiter.h.

236 {
237 std::shared_lock<std::shared_mutex> lock(mutex_);
238 return buckets_.size();
239 }

References buckets_, and mutex_.

◆ config()

rate_limiter_config kcenon::network::rate_limiter::config ( ) const
inlinenodiscard

Get current configuration.

Returns
Current configuration
Examples
/home/runner/work/network_system/network_system/src/internal/utils/rate_limiter.h.

Definition at line 254 of file rate_limiter.h.

254 {
255 std::shared_lock<std::shared_mutex> lock(mutex_);
256 return config_;
257 }

References config_, and mutex_.

Referenced by set_config().

Here is the caller graph for this function:

◆ maybe_cleanup()

void kcenon::network::rate_limiter::maybe_cleanup ( std::chrono::steady_clock::time_point now)
inlineprivate
Examples
/home/runner/work/network_system/network_system/src/internal/utils/rate_limiter.h.

Definition at line 265 of file rate_limiter.h.

265 {
266 // Cleanup at most once per minute
267 auto since_cleanup = std::chrono::duration_cast<std::chrono::seconds>(
268 now - last_cleanup_);
269
270 if (since_cleanup < std::chrono::seconds(60)) {
271 return;
272 }
273
274 last_cleanup_ = now;
275
276 // Remove stale entries
277 for (auto it = buckets_.begin(); it != buckets_.end();) {
278 auto since_refill = std::chrono::duration_cast<std::chrono::seconds>(
279 now - it->second.last_refill);
280
281 if (since_refill > config_.stale_timeout) {
282 it = buckets_.erase(it);
283 } else {
284 ++it;
285 }
286 }
287 }
std::chrono::seconds stale_timeout
Stale entry expiration time.

References buckets_, config_, last_cleanup_, and kcenon::network::rate_limiter_config::stale_timeout.

Referenced by allow().

Here is the caller graph for this function:

◆ remaining_tokens()

double kcenon::network::rate_limiter::remaining_tokens ( std::string_view client_id) const
inlinenodiscard

Get remaining tokens for a client.

Parameters
client_idClient identifier
Returns
Number of remaining tokens
Examples
/home/runner/work/network_system/network_system/src/internal/utils/rate_limiter.h.

Definition at line 195 of file rate_limiter.h.

195 {
196 std::shared_lock<std::shared_mutex> lock(mutex_);
197
198 auto it = buckets_.find(std::string(client_id));
199 if (it == buckets_.end()) {
200 return static_cast<double>(config_.burst_size);
201 }
202
203 auto now = std::chrono::steady_clock::now();
204 auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(
205 now - it->second.last_refill);
206
207 double tokens_to_add = elapsed.count() *
208 (static_cast<double>(config_.max_requests_per_second) / 1000.0);
209
210 return std::min(
211 static_cast<double>(config_.burst_size),
212 it->second.tokens + tokens_to_add);
213 }

References buckets_, kcenon::network::rate_limiter_config::burst_size, config_, kcenon::network::rate_limiter_config::max_requests_per_second, and mutex_.

◆ reset()

void kcenon::network::rate_limiter::reset ( std::string_view client_id)
inline

Reset rate limit for a specific client.

Parameters
client_idClient identifier
Examples
/home/runner/work/network_system/network_system/src/internal/utils/rate_limiter.h.

Definition at line 219 of file rate_limiter.h.

219 {
220 std::unique_lock<std::shared_mutex> lock(mutex_);
221 buckets_.erase(std::string(client_id));
222 }

References buckets_, and mutex_.

◆ reset_all()

void kcenon::network::rate_limiter::reset_all ( )
inline

Reset all rate limits.

Examples
/home/runner/work/network_system/network_system/src/internal/utils/rate_limiter.h.

Definition at line 227 of file rate_limiter.h.

227 {
228 std::unique_lock<std::shared_mutex> lock(mutex_);
229 buckets_.clear();
230 }

References buckets_, and mutex_.

◆ set_config()

void kcenon::network::rate_limiter::set_config ( rate_limiter_config config)
inline

Update configuration.

Parameters
configNew configuration
Examples
/home/runner/work/network_system/network_system/src/internal/utils/rate_limiter.h.

Definition at line 245 of file rate_limiter.h.

245 {
246 std::unique_lock<std::shared_mutex> lock(mutex_);
247 config_ = std::move(config);
248 }

References config(), config_, and mutex_.

Here is the call graph for this function:

◆ would_allow()

bool kcenon::network::rate_limiter::would_allow ( std::string_view client_id) const
inlinenodiscard

Check if request would be allowed (without consuming token)

Parameters
client_idClient identifier
Returns
true if a request would be allowed
Examples
/home/runner/work/network_system/network_system/src/internal/utils/rate_limiter.h.

Definition at line 167 of file rate_limiter.h.

167 {
168 std::shared_lock<std::shared_mutex> lock(mutex_);
169
170 auto it = buckets_.find(std::string(client_id));
171 if (it == buckets_.end()) {
172 return true; // New client would have full bucket
173 }
174
175 auto now = std::chrono::steady_clock::now();
176 auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(
177 now - it->second.last_refill);
178
179 double tokens_to_add = elapsed.count() *
180 (static_cast<double>(config_.max_requests_per_second) / 1000.0);
181
182 double available = std::min(
183 static_cast<double>(config_.burst_size),
184 it->second.tokens + tokens_to_add);
185
186 return available >= 1.0;
187 }

References buckets_, kcenon::network::rate_limiter_config::burst_size, config_, kcenon::network::rate_limiter_config::max_requests_per_second, and mutex_.

Member Data Documentation

◆ buckets_

std::unordered_map<std::string, bucket> kcenon::network::rate_limiter::buckets_
private

◆ config_

◆ last_cleanup_

std::chrono::steady_clock::time_point kcenon::network::rate_limiter::last_cleanup_
private

◆ mutex_

std::shared_mutex kcenon::network::rate_limiter::mutex_
mutableprivate

The documentation for this class was generated from the following file: