use super::{RequestAdmission, TokenRecord};
pub(super) fn consume_request(record: Option<&mut TokenRecord>) -> bool {
let Some(record) = record else {
return true;
};
if record
.max_requests
.is_some_and(|max| record.used_requests >= max)
{
return false;
}
record.used_requests = record.used_requests.saturating_add(1);
true
}
pub(super) fn admit_request_reserving(
record: Option<&mut TokenRecord>,
now: i64,
reserve: u64,
) -> RequestAdmission {
let Some(record) = record else {
return RequestAdmission::Admitted;
};
if record
.max_requests
.is_some_and(|max| record.used_requests >= max)
{
return RequestAdmission::RequestLimitExceeded;
}
if let Some(max) = record.max_tokens {
let committed = record.used_tokens.saturating_add(record.reserved_tokens);
if committed >= max || committed.saturating_add(reserve) > max {
return RequestAdmission::TokenLimitExceeded;
}
}
if let Some(max) = record.rate_limit_per_minute {
if now.saturating_sub(record.rate_window_started_at) >= 60 {
record.rate_window_started_at = now;
record.rate_window_requests = 0;
}
if record.rate_window_requests >= max {
return RequestAdmission::RateLimitExceeded;
}
record.rate_window_requests = record.rate_window_requests.saturating_add(1);
}
record.used_requests = record.used_requests.saturating_add(1);
record.reserved_tokens = record.reserved_tokens.saturating_add(reserve);
RequestAdmission::Admitted
}
pub(super) const fn add_token_usage(record: Option<&mut TokenRecord>, tokens: u64) {
if let Some(record) = record {
record.used_tokens = record.used_tokens.saturating_add(tokens);
}
}
pub(super) const fn settle_token_usage(
record: Option<&mut TokenRecord>,
reserved: u64,
actual: u64,
) {
if let Some(record) = record {
record.reserved_tokens = record.reserved_tokens.saturating_sub(reserved);
record.used_tokens = record.used_tokens.saturating_add(actual);
}
}
pub(super) fn merge_safer_record(current: &mut TokenRecord, other: &TokenRecord) {
current.revoked |= other.revoked;
current.used_requests = current.used_requests.max(other.used_requests);
current.used_tokens = current.used_tokens.max(other.used_tokens);
current.reserved_tokens = current.reserved_tokens.max(other.reserved_tokens);
if other.rate_window_started_at > current.rate_window_started_at {
current.rate_window_started_at = other.rate_window_started_at;
current.rate_window_requests = other.rate_window_requests;
} else if other.rate_window_started_at == current.rate_window_started_at {
current.rate_window_requests = current.rate_window_requests.max(other.rate_window_requests);
}
}