Files
fastapi-traffic/docs/api/backends.rst
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

267 lines
6.2 KiB
ReStructuredText

Backends API
============
Storage backends for rate limit state.
Backend (Base Class)
--------------------
.. py:class:: Backend
Abstract base class for rate limit storage backends.
All backends must implement these methods:
.. py:method:: get(key)
:async:
Get the current state for a key.
:param key: The rate limit key.
:type key: str
:returns: The stored state dictionary or None if not found.
:rtype: dict[str, Any] | None
.. py:method:: set(key, value, *, ttl)
:async:
Set the state for a key with TTL.
:param key: The rate limit key.
:type key: str
:param value: The state dictionary to store.
:type value: dict[str, Any]
:param ttl: Time-to-live in seconds.
:type ttl: float
.. py:method:: delete(key)
:async:
Delete the state for a key.
:param key: The rate limit key.
:type key: str
.. py:method:: exists(key)
:async:
Check if a key exists.
:param key: The rate limit key.
:type key: str
:returns: True if the key exists.
:rtype: bool
.. py:method:: increment(key, amount=1)
:async:
Atomically increment a counter.
:param key: The rate limit key.
:type key: str
:param amount: The amount to increment by.
:type amount: int
:returns: The new value after incrementing.
:rtype: int
.. py:method:: clear()
:async:
Clear all rate limit data.
.. py:method:: close()
:async:
Close the backend connection.
Backends support async context manager protocol:
.. code-block:: python
async with MemoryBackend() as backend:
await backend.set("key", {"count": 1}, ttl=60)
MemoryBackend
-------------
.. py:class:: MemoryBackend(max_size=10000, cleanup_interval=60)
In-memory storage backend with LRU eviction and TTL cleanup.
:param max_size: Maximum number of keys to store.
:type max_size: int
:param cleanup_interval: How often to clean expired entries (seconds).
:type cleanup_interval: float
**Usage:**
.. code-block:: python
from fastapi_traffic import MemoryBackend, RateLimiter
backend = MemoryBackend(max_size=10000)
limiter = RateLimiter(backend)
.. py:method:: get_stats()
Get statistics about the backend.
:returns: Dictionary with stats like key count, memory usage.
:rtype: dict[str, Any]
.. py:method:: start_cleanup()
:async:
Start the background cleanup task.
.. py:method:: stop_cleanup()
:async:
Stop the background cleanup task.
SQLiteBackend
-------------
.. py:class:: SQLiteBackend(db_path, cleanup_interval=300)
SQLite storage backend for persistent rate limiting.
:param db_path: Path to the SQLite database file.
:type db_path: str | Path
:param cleanup_interval: How often to clean expired entries (seconds).
:type cleanup_interval: float
**Usage:**
.. code-block:: python
from fastapi_traffic import SQLiteBackend, RateLimiter
backend = SQLiteBackend("rate_limits.db")
limiter = RateLimiter(backend)
@app.on_event("startup")
async def startup():
await limiter.initialize()
@app.on_event("shutdown")
async def shutdown():
await limiter.close()
.. py:method:: initialize()
:async:
Initialize the database schema.
Features:
- WAL mode for better concurrent performance
- Automatic schema creation
- Connection pooling
- Background cleanup of expired entries
RedisBackend
------------
.. py:class:: RedisBackend
Redis storage backend for distributed rate limiting.
.. py:method:: from_url(url, *, key_prefix="", **kwargs)
:classmethod:
Create a RedisBackend from a Redis URL. This is an async classmethod.
:param url: Redis connection URL.
:type url: str
:param key_prefix: Prefix for all keys.
:type key_prefix: str
:returns: Configured RedisBackend instance.
:rtype: RedisBackend
**Usage:**
.. code-block:: python
from fastapi_traffic.backends.redis import RedisBackend
from fastapi_traffic import RateLimiter
@app.on_event("startup")
async def startup():
backend = await RedisBackend.from_url("redis://localhost:6379/0")
limiter = RateLimiter(backend)
**Connection examples:**
.. code-block:: python
# Simple connection
backend = await RedisBackend.from_url("redis://localhost:6379/0")
# With password
backend = await RedisBackend.from_url("redis://:password@localhost:6379/0")
# With key prefix
backend = await RedisBackend.from_url(
"redis://localhost:6379/0",
key_prefix="myapp:ratelimit:",
)
.. py:method:: get_stats()
:async:
Get statistics about the Redis backend.
:returns: Dictionary with stats like key count, memory usage.
:rtype: dict[str, Any]
Features:
- Atomic operations via Lua scripts
- Automatic key expiration
- Connection pooling
- Support for Redis Sentinel and Cluster
Implementing Custom Backends
----------------------------
To create a custom backend, inherit from ``Backend`` and implement all abstract
methods:
.. code-block:: python
from fastapi_traffic.backends.base import Backend
from typing import Any
class MyBackend(Backend):
async def get(self, key: str) -> dict[str, Any] | None:
# Retrieve state from your storage
pass
async def set(self, key: str, value: dict[str, Any], *, ttl: float) -> None:
# Store state with expiration
pass
async def delete(self, key: str) -> None:
# Remove a key
pass
async def exists(self, key: str) -> bool:
# Check if key exists
pass
async def increment(self, key: str, amount: int = 1) -> int:
# Atomically increment (important for accuracy)
pass
async def clear(self) -> None:
# Clear all data
pass
async def close(self) -> None:
# Clean up connections
pass
The ``value`` dictionary contains algorithm-specific state. Your backend should
serialize it appropriately (JSON works well for most cases).