Files
zanewalker f3453cb0fc release: bump version to 0.3.0
- Refactor Redis backend connection handling and pool management
- Update algorithm implementations with improved type annotations
- Enhance config loader validation with stricter Pydantic schemas
- Improve decorator and middleware error handling
- Expand example scripts with better docstrings and usage patterns
- Add new 00_basic_usage.py example for quick start
- Reorganize examples directory structure
- Fix type annotation inconsistencies across core modules
- Update dependencies in pyproject.toml
2026-03-17 21:04:34 +00:00

90 lines
1.9 KiB
Python

"""Data models for rate limiting."""
from __future__ import annotations
from dataclasses import dataclass, field
from enum import Enum
from typing import Any
class KeyType(str, Enum):
"""Type of key extraction for rate limiting."""
IP = "ip"
USER = "user"
API_KEY = "api_key"
ENDPOINT = "endpoint"
CUSTOM = "custom"
@dataclass(frozen=True, slots=True)
class RateLimitInfo:
"""Information about the current rate limit state."""
limit: int
remaining: int
reset_at: float
retry_after: float | None = None
window_size: float = 60.0
def to_headers(self) -> dict[str, str]:
"""Convert rate limit info to HTTP headers."""
headers: dict[str, str] = {
"X-RateLimit-Limit": str(self.limit),
"X-RateLimit-Remaining": str(max(0, self.remaining)),
"X-RateLimit-Reset": str(int(self.reset_at)),
}
if self.retry_after is not None:
headers["Retry-After"] = str(int(self.retry_after))
return headers
@dataclass(frozen=True, slots=True)
class RateLimitResult:
"""Result of a rate limit check."""
allowed: bool
info: RateLimitInfo
key: str
@dataclass(slots=True)
class TokenBucketState:
"""State for token bucket algorithm."""
tokens: float
last_update: float
@dataclass(slots=True)
class SlidingWindowState:
"""State for sliding window algorithm."""
timestamps: list[float] = field(default_factory=list[float])
count: int = 0
@dataclass(slots=True)
class FixedWindowState:
"""State for fixed window algorithm."""
count: int
window_start: float
@dataclass(slots=True)
class LeakyBucketState:
"""State for leaky bucket algorithm."""
water_level: float
last_update: float
@dataclass(frozen=True, slots=True)
class BackendRecord:
"""Generic record stored in backends."""
key: str
data: dict[str, Any]
expires_at: float