Kurlyk
Loading...
Searching...
No Matches
kurlyk::HttpRateLimiter Class Reference

Manages rate limits for HTTP requests. More...

#include <HttpRateLimiter.hpp>

Classes

struct  KeyState
 Per-key mutable runtime state inside a rate limit. More...
struct  LimitData
 Immutable limit parameters plus per-key mutable state. More...

Public Member Functions

HttpRateLimitHandlePtr create_limit_handle (long requests_per_period, long period_ms, bool sequential=false)
 Creates a new rate limit and returns its RAII handle.
long create_limit (long requests_per_period, long period_ms)
 Legacy API: creates a new rate limit and returns only its ID.
bool remove_limit (long limit_id)
 Releases manager-owned handle for the specified limit ID.
bool remove_limit (const HttpRateLimitHandlePtr &handle)
 Releases manager-owned handle for the specified limit handle.
HttpRateLimitHandlePtr get_limit (long limit_id)
 Returns manager-owned handle by ID.
bool allow_request (const HttpRateLimitHandlePtr &general_limit, const HttpRateLimitHandlePtr &specific_limit, uint64_t in_flight_token, const std::string &general_key, const std::string &specific_key)
 Checks if a request is allowed by two optional rate-limit handles with in-flight token tracking for sequential limits.
bool allow_request (const HttpRateLimitHandlePtr &general_limit, const HttpRateLimitHandlePtr &specific_limit)
 Handle-based overload without explicit token or keys (token = 0, keys empty).
bool allow_request (long general_rate_limit_id, long specific_rate_limit_id)
 Legacy API: checks if request is allowed by two limit IDs.
void release_request (const HttpRateLimitHandlePtr &general_limit, const HttpRateLimitHandlePtr &specific_limit, uint64_t in_flight_token, const std::string &general_key, const std::string &specific_key)
 Releases in-flight tokens for sequential rate limits.
void release_request (const HttpRateLimitHandlePtr &general_limit, const HttpRateLimitHandlePtr &specific_limit, uint64_t in_flight_token)
 Legacy overload without keys.
template<typename Duration = std::chrono::milliseconds>
RateLimitDelay< Duration > time_until_next_allowed (const HttpRateLimitHandlePtr &general_limit, const HttpRateLimitHandlePtr &specific_limit, const std::string &general_key, const std::string &specific_key)
template<typename Duration = std::chrono::milliseconds>
RateLimitDelay< Duration > time_until_next_allowed (const HttpRateLimitHandlePtr &general_limit, const HttpRateLimitHandlePtr &specific_limit)
 Legacy overload without explicit partition keys (uses default shared state).
template<typename Duration = std::chrono::milliseconds>
RateLimitDelay< Duration > time_until_next_allowed (long general_rate_limit_id, long specific_rate_limit_id)
 Legacy API: calculates delay by limit IDs.
template<typename Duration = std::chrono::milliseconds>
RateLimitDelay< Duration > time_until_any_limit_allows ()
 Finds the shortest delay among all physically alive limits.

Private Types

using time_point_t = std::chrono::steady_clock::time_point

Private Member Functions

bool remove_limit_internal (long limit_id)
 Marks a limit as removed and erases it only when no key state remains.
KeyStateget_key_state (LimitData &limit, const std::string &key)
 Looks up a KeyState by key, creating it lazily if necessary.
const KeyStatefind_key_state (const LimitData &limit, const std::string &key) const
 Looks up a KeyState by key for read-only access (no insertion).
bool can_pass (const LimitData &limit, const std::string &key, uint64_t token, const time_point_t &now) const
 Checks if a key within a limit can pass both sequential and count/period constraints.
bool check_key (const LimitData &limit_data, const KeyState &state, const time_point_t &now) const
void commit_limit (LimitData &limit, const std::string &key, uint64_t token, const time_point_t &now)
 Commits in-flight token and count/period state after a successful can_pass.
void update_key (LimitData &limit_data, KeyState &state, const time_point_t &now)
void release_key (LimitData &limit, const std::string &key, uint64_t token)
 Releases an in-flight token from a specific key and erases the key if it has no runtime state.
template<typename Duration>
Duration time_until_limit_allows (const LimitData &limit, const std::string &key, const time_point_t &now) const
template<typename Duration>
Duration time_until_key_allows (const LimitData &limit, const KeyState &state, const time_point_t &now) const
void gc_stale_keys (const time_point_t &now)
 Erases keys that are empty or whose period has expired.

Private Attributes

std::mutex m_mutex
long m_next_id = 1
std::unordered_map< long, LimitDatam_limits
 Physically alive limit data.
std::unordered_map< long, HttpRateLimitHandlePtrm_owned_handles
 Manager-owned handles for limits created through create_limit_handle().
size_t m_gc_counter = 0

Detailed Description

Manages rate limits for HTTP requests.

Rate limits are referenced by RAII handles. A limit remains physically present while at least one HttpRateLimitHandlePtr exists. Calling remove_limit(id) only releases the manager-owned handle. If pending or active requests still hold copied handles, the limit remains active until those requests are destroyed.

Each limit can be partitioned by string keys. Requests sharing the same key within the same limit ID share rate-limit state; different keys are independent. An empty key maps to the default shared state.

Definition at line 22 of file HttpRateLimiter.hpp.

Member Typedef Documentation

◆ time_point_t

using kurlyk::HttpRateLimiter::time_point_t = std::chrono::steady_clock::time_point
private

Definition at line 376 of file HttpRateLimiter.hpp.

Member Function Documentation

◆ allow_request() [1/3]

bool kurlyk::HttpRateLimiter::allow_request ( const HttpRateLimitHandlePtr & general_limit,
const HttpRateLimitHandlePtr & specific_limit )
inline

Handle-based overload without explicit token or keys (token = 0, keys empty).

Definition at line 194 of file HttpRateLimiter.hpp.

◆ allow_request() [2/3]

bool kurlyk::HttpRateLimiter::allow_request ( const HttpRateLimitHandlePtr & general_limit,
const HttpRateLimitHandlePtr & specific_limit,
uint64_t in_flight_token,
const std::string & general_key,
const std::string & specific_key )
inline

Checks if a request is allowed by two optional rate-limit handles with in-flight token tracking for sequential limits.

Counters and in-flight sets are updated only if both limits allow the request.

Parameters
general_limitGeneral rate-limit handle (may be empty).
specific_limitSpecific rate-limit handle (may be empty).
in_flight_tokenToken identifying the in-flight request; 0 skips sequential checks.
general_keyPartition key for the general limit; empty means default state.
specific_keyPartition key for the specific limit; empty means default state.
Returns
`true` if the request is allowed, `false` otherwise (state unchanged on failure).

Definition at line 128 of file HttpRateLimiter.hpp.

◆ allow_request() [3/3]

bool kurlyk::HttpRateLimiter::allow_request ( long general_rate_limit_id,
long specific_rate_limit_id )
inline

Legacy API: checks if request is allowed by two limit IDs.

Warning
Prefer handle-based overload. ID-based requests do not keep limits alive by themselves.

Definition at line 205 of file HttpRateLimiter.hpp.

◆ can_pass()

bool kurlyk::HttpRateLimiter::can_pass ( const LimitData & limit,
const std::string & key,
uint64_t token,
const time_point_t & now ) const
inlineprivate

Checks if a key within a limit can pass both sequential and count/period constraints.

Definition at line 434 of file HttpRateLimiter.hpp.

◆ check_key()

bool kurlyk::HttpRateLimiter::check_key ( const LimitData & limit_data,
const KeyState & state,
const time_point_t & now ) const
inlineprivate

Definition at line 452 of file HttpRateLimiter.hpp.

◆ commit_limit()

void kurlyk::HttpRateLimiter::commit_limit ( LimitData & limit,
const std::string & key,
uint64_t token,
const time_point_t & now )
inlineprivate

Commits in-flight token and count/period state after a successful can_pass.

Definition at line 470 of file HttpRateLimiter.hpp.

◆ create_limit()

long kurlyk::HttpRateLimiter::create_limit ( long requests_per_period,
long period_ms )
inline

Legacy API: creates a new rate limit and returns only its ID.

Warning
Prefer create_limit_handle(). Requests that only store the ID do not keep the limit alive by themselves. The manager-owned handle keeps the limit alive until remove_limit(id) is called.

Definition at line 63 of file HttpRateLimiter.hpp.

◆ create_limit_handle()

HttpRateLimitHandlePtr kurlyk::HttpRateLimiter::create_limit_handle ( long requests_per_period,
long period_ms,
bool sequential = false )
inline

Creates a new rate limit and returns its RAII handle.

Parameters
requests_per_periodMaximum requests allowed within the period. 0 means unlimited.
period_msPeriod duration in milliseconds.
sequentialWhen `true`, no other request sharing this limit may start until the current request (including all its retries) has finished.
Returns
Shared RAII handle for the created limit.

Definition at line 30 of file HttpRateLimiter.hpp.

◆ find_key_state()

const KeyState * kurlyk::HttpRateLimiter::find_key_state ( const LimitData & limit,
const std::string & key ) const
inlineprivate

Looks up a KeyState by key for read-only access (no insertion).

Definition at line 425 of file HttpRateLimiter.hpp.

◆ gc_stale_keys()

void kurlyk::HttpRateLimiter::gc_stale_keys ( const time_point_t & now)
inlineprivate

Erases keys that are empty or whose period has expired.

Definition at line 571 of file HttpRateLimiter.hpp.

◆ get_key_state()

KeyState & kurlyk::HttpRateLimiter::get_key_state ( LimitData & limit,
const std::string & key )
inlineprivate

Looks up a KeyState by key, creating it lazily if necessary.

Definition at line 420 of file HttpRateLimiter.hpp.

◆ get_limit()

HttpRateLimitHandlePtr kurlyk::HttpRateLimiter::get_limit ( long limit_id)
inline

Returns manager-owned handle by ID.

Note
This is mainly for compatibility with legacy ID-based API.

Definition at line 107 of file HttpRateLimiter.hpp.

◆ release_key()

void kurlyk::HttpRateLimiter::release_key ( LimitData & limit,
const std::string & key,
uint64_t token )
inlineprivate

Releases an in-flight token from a specific key and erases the key if it has no runtime state.

Definition at line 501 of file HttpRateLimiter.hpp.

◆ release_request() [1/2]

void kurlyk::HttpRateLimiter::release_request ( const HttpRateLimitHandlePtr & general_limit,
const HttpRateLimitHandlePtr & specific_limit,
uint64_t in_flight_token )
inline

Legacy overload without keys.

Definition at line 254 of file HttpRateLimiter.hpp.

◆ release_request() [2/2]

void kurlyk::HttpRateLimiter::release_request ( const HttpRateLimitHandlePtr & general_limit,
const HttpRateLimitHandlePtr & specific_limit,
uint64_t in_flight_token,
const std::string & general_key,
const std::string & specific_key )
inline

Releases in-flight tokens for sequential rate limits.

Must be called when a request finishes (including after cancellation or destruction).

Parameters
general_limitGeneral rate-limit handle (may be empty).
specific_limitSpecific rate-limit handle (may be empty).
in_flight_tokenToken identifying the in-flight request; 0 is a no-op.
general_keyPartition key for the general limit.
specific_keyPartition key for the specific limit.

Definition at line 223 of file HttpRateLimiter.hpp.

◆ remove_limit() [1/2]

bool kurlyk::HttpRateLimiter::remove_limit ( const HttpRateLimitHandlePtr & handle)
inline

Releases manager-owned handle for the specified limit handle.

Parameters
handleRate-limit handle.
Returns
`true` if manager-owned handle was found and released.

Definition at line 100 of file HttpRateLimiter.hpp.

◆ remove_limit() [2/2]

bool kurlyk::HttpRateLimiter::remove_limit ( long limit_id)
inline

Releases manager-owned handle for the specified limit ID.

This does not necessarily erase LimitData immediately. If any pending or active request still holds a copied handle, the limit stays alive. Physical erase happens from HttpRateLimitHandle destructor.

Parameters
limit_idRate-limit ID.
Returns
`true` if manager-owned handle was found and released.

Definition at line 76 of file HttpRateLimiter.hpp.

◆ remove_limit_internal()

bool kurlyk::HttpRateLimiter::remove_limit_internal ( long limit_id)
inlineprivate

Marks a limit as removed and erases it only when no key state remains.

This method is intentionally private. It must be called only from HttpRateLimitHandle destruction path.

Note
HttpRequestManager (and its embedded HttpRateLimiter) is intentionally never destroyed. The this captured in HttpRateLimitHandle destructor is therefore always valid. Changing the singleton to a destructible form requires replacing this raw capture.

Definition at line 404 of file HttpRateLimiter.hpp.

◆ time_until_any_limit_allows()

template<typename Duration = std::chrono::milliseconds>
RateLimitDelay< Duration > kurlyk::HttpRateLimiter::time_until_any_limit_allows ( )
inline

Finds the shortest delay among all physically alive limits.

Template Parameters
DurationDuration type; defaults to std::chrono::milliseconds.
Returns
RateLimitDelay where duration is the minimum positive delay across all keys of all limits. If no limit reports a positive delay, duration is 0. sequential_blocked is true when the selected positive delay is Duration::max(), meaning no finite positive delay was found among currently delayed keys.

Definition at line 341 of file HttpRateLimiter.hpp.

◆ time_until_key_allows()

template<typename Duration>
Duration kurlyk::HttpRateLimiter::time_until_key_allows ( const LimitData & limit,
const KeyState & state,
const time_point_t & now ) const
inlineprivate

Definition at line 540 of file HttpRateLimiter.hpp.

◆ time_until_limit_allows()

template<typename Duration>
Duration kurlyk::HttpRateLimiter::time_until_limit_allows ( const LimitData & limit,
const std::string & key,
const time_point_t & now ) const
inlineprivate

Definition at line 520 of file HttpRateLimiter.hpp.

◆ time_until_next_allowed() [1/3]

template<typename Duration = std::chrono::milliseconds>
RateLimitDelay< Duration > kurlyk::HttpRateLimiter::time_until_next_allowed ( const HttpRateLimitHandlePtr & general_limit,
const HttpRateLimitHandlePtr & specific_limit )
inline

Legacy overload without explicit partition keys (uses default shared state).

Definition at line 310 of file HttpRateLimiter.hpp.

◆ time_until_next_allowed() [2/3]

template<typename Duration = std::chrono::milliseconds>
RateLimitDelay< Duration > kurlyk::HttpRateLimiter::time_until_next_allowed ( const HttpRateLimitHandlePtr & general_limit,
const HttpRateLimitHandlePtr & specific_limit,
const std::string & general_key,
const std::string & specific_key )
inline
Template Parameters
DurationDuration type; defaults to std::chrono::milliseconds.
Parameters
general_limitGeneral rate-limit handle (may be empty).
specific_limitSpecific rate-limit handle (may be empty).
general_keyPartition key for the general limit; empty means default shared state.
specific_keyPartition key for the specific limit; empty means default shared state.
Returns
RateLimitDelay describing the maximum delay across both dimensions. duration is 0 only when all present dimensions allow immediately. sequential_blocked is true when at least one dimension is blocked by a sequential in-flight request (duration == Duration::max()).

Definition at line 271 of file HttpRateLimiter.hpp.

◆ time_until_next_allowed() [3/3]

template<typename Duration = std::chrono::milliseconds>
RateLimitDelay< Duration > kurlyk::HttpRateLimiter::time_until_next_allowed ( long general_rate_limit_id,
long specific_rate_limit_id )
inline

Legacy API: calculates delay by limit IDs.

Template Parameters
DurationDuration type; defaults to std::chrono::milliseconds.
Parameters
general_rate_limit_idGeneral rate-limit ID.
specific_rate_limit_idSpecific rate-limit ID.
Returns
RateLimitDelay describing the maximum delay across both dimensions.
Warning
Prefer handle-based overload. ID-based requests do not keep limits alive.

Definition at line 324 of file HttpRateLimiter.hpp.

◆ update_key()

void kurlyk::HttpRateLimiter::update_key ( LimitData & limit_data,
KeyState & state,
const time_point_t & now )
inlineprivate

Definition at line 482 of file HttpRateLimiter.hpp.

Member Data Documentation

◆ m_gc_counter

size_t kurlyk::HttpRateLimiter::m_gc_counter = 0
private

Definition at line 617 of file HttpRateLimiter.hpp.

◆ m_limits

std::unordered_map<long, LimitData> kurlyk::HttpRateLimiter::m_limits
private

Physically alive limit data.

A record remains here while at least one HttpRateLimitHandlePtr exists.

Definition at line 609 of file HttpRateLimiter.hpp.

◆ m_mutex

std::mutex kurlyk::HttpRateLimiter::m_mutex
mutableprivate

Definition at line 602 of file HttpRateLimiter.hpp.

◆ m_next_id

long kurlyk::HttpRateLimiter::m_next_id = 1
private

Definition at line 604 of file HttpRateLimiter.hpp.

◆ m_owned_handles

std::unordered_map<long, HttpRateLimitHandlePtr> kurlyk::HttpRateLimiter::m_owned_handles
private

Manager-owned handles for limits created through create_limit_handle().

remove_limit(id) releases the handle from this map. If requests still hold copies, physical data stays alive until the last copy is destroyed.

Definition at line 615 of file HttpRateLimiter.hpp.


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