Skip to main content

Utility for handling rate limiting in a centralized manner

Project description

CentralizedRateLimiter

Python 3.9+ License Code style: black Coverage PyPI version

A robust, centralized rate limiting utility for Python applications that need precise control over API request rates with built-in retry mechanisms and support for multiple rate limits.

๐Ÿ”ง Installation

pip install centralized-rate-limiter

๐ŸŒŸ Features

  • Multiple Rate Limits: Support for multiple concurrent rate limits (e.g., per-second, per-minute, per-hour)
  • Centralized Configuration: Set rate limiting parameters once and reuse across your application for all request methods
  • Comprehensive Retry Logic: Built-in exponential backoff and configurable retry attempts
  • Thread-Safe: Reliable rate limiting in multi-threaded environments
  • Flexible HTTP Support: Works with all standard HTTP methods
  • Session Management: Extends requests.Session for seamless integration
  • Type Hints: Full type annotation support for better IDE integration

๐ŸŽฏ Quick Start

from centralized_rate_limiter import get_rate_limiter

# Create a rate limiter with single rate limit (backward compatible)
rate_limiter = get_rate_limiter(
    requests_per_second=10,
    total_retries=5,
    backoff_factor=0.25
)

# Create a rate limiter with multiple rate limits
rate_limiter = get_rate_limiter(
    requests_per_second=10,  # Base rate: 10 requests per second
    additional_limits=[
        (60, 60),     # 60 requests per minute
        (2000, 3600)  # 2000 requests per hour
    ],
    total_retries=5,
    backoff_factor=0.25
)

# Use it for your API calls
response = rate_limiter.get('https://api.example.com/data')

# Works with all HTTP methods
post_response = rate_limiter.post(
    'https://api.example.com/create',
    json={'key': 'value'}
)

๐Ÿ”ง Advanced Usage

Custom Configuration

from centralized_rate_limiter import RateLimitedSession

# Create a session with multiple rate limits
session = RateLimitedSession(
    requests_per_second=5,
    additional_limits=[
        (100, 60),    # 100 requests per minute
        (2000, 3600)  # 2000 requests per hour
    ],
    total_retries=3,
    backoff_factor=0.5
)

# Use session in your application
responses = []
for endpoint in endpoints:
    response = session.get(endpoint)
    responses.append(response)

Error Handling

from requests.exceptions import RetryError

try:
    response = rate_limiter.get('https://api.example.com/data')
    data = response.json()
except RetryError:
    print("Max retries exceeded")
except Exception as e:
    print(f"An error occurred: {e}")

๐Ÿ“Š Configuration Parameters

Parameter Type Default Description
requests_per_second int 10 Maximum number of requests allowed per second
additional_limits List[Tuple[int, float]] None Additional rate limits as (max_calls, period) tuples
total_retries int 5 Maximum number of retry attempts for failed requests
backoff_factor float 0.25 Multiplier for exponential backoff between retries

Additional Limits Format

The additional_limits parameter accepts a list of tuples, where each tuple contains:

  • First element: Maximum number of calls allowed in the period
  • Second element: Period in seconds

Example:

additional_limits=[
    (60, 60),     # 60 calls per 60 seconds (per minute)
    (2000, 3600)  # 2000 calls per 3600 seconds (per hour)
]

๐Ÿค” When to Use This vs. Other Solutions

Use CentralizedRateLimiter When You Need:

  1. Multiple Rate Limits

    • You need to handle multiple concurrent rate limits (e.g., per-second, per-minute, per-hour)
    • You want to enforce different rate limits for different time windows
    • You need to comply with complex API rate limit requirements
  2. Centralized Rate Limiting and Retry Logic

    • You want a single solution that handles both rate limiting and retries
    • You want a single rate limit for all your requests methods
    • You need fine-grained control over retry behavior
  3. Thread-Safe Operation

    • Your application makes API calls from multiple threads
    • You need reliable rate limiting in concurrent scenarios
  4. Session Management

    • You want to maintain session state across requests
    • You need to reuse connections for better performance

Consider Alternatives When:

  1. Distributed Rate Limiting Required

    • Consider python-redis-rate-limit for distributed systems
    • Use Flask-Limiter for API endpoint protection
  2. Simpler Requirements

    • Use requests-ratelimiter for basic rate limiting
    • Use backoff package for simple retry logic
  3. Async Operation

    • Consider aiohttp with aiohttp-client-manager
    • Use asyncio based solutions for async workflows

๐Ÿ” How It Works

The library uses a combination of:

  • Thread-safe rate limiting for multiple concurrent limits
  • Decorator-based rate limiting using the ratelimit package
  • urllib3.util.Retry for configurable retry behavior
  • Custom session management extending requests.Session

Example retry sequence:

Request 1 (fails) โ†’ Wait 0.25s โ†’ Retry 1 (fails) โ†’ Wait 0.5s โ†’ Retry 2 (succeeds)

Example with multiple rate limits:

# Configuration
limits = [
    (60, 60),     # 60 requests per minute
    (2000, 3600)  # 2000 requests per hour
]

# The rate limiter will ensure all limits are respected:
# - No more than 60 requests in any 60-second window
# - No more than 2000 requests in any 3600-second (1 hour) window

๐Ÿ› ๏ธ Development

Prerequisites

  • Python 3.7+
  • Make (optional, but recommended)
  • Git

Setting Up Development Environment

  1. Clone the repository:
git clone https://github.com/waddafunk/CentralizedRateLimiter.git
cd CentralizedRateLimiter
  1. Install development dependencies:
make dev-install

Or without make:

python -m pip install -e ".[dev]"

Development Tools

The project uses several development tools, all configured in pyproject.toml:

Code Formatting

  • Black: Code formatter with a line length of 88 characters
  • isort: Import statement organizer, configured to work with Black
  • pyupgrade: Automatically upgrades Python syntax for newer versions
# Format all code
make format

or without make

# Individual tools
python -m black .
python -m isort .
python -m pyupgrade --py37-plus **/*.py

Code Quality

  • pylint: Static code analysis
  • flake8: Style guide enforcement
# Run all linters
make lint

or without make

python -m pylint centralized_rate_limiter tests
python -m flake8 centralized_rate_limiter tests

Testing

  • pytest: Test framework
  • pytest-cov: Coverage reporting
  • responses: HTTP request mocking
# Run tests with coverage
make test

or without make

make coverage

Development Workflow

  1. Create a new branch for your feature:
git checkout -b feature/your-feature-name
  1. Make your changes and ensure quality:
make format  # Format code
make lint    # Check code quality
make test    # Run tests
# Or run all checks at once:
make all
  1. Build and check the package:
make build
  1. Submit a pull request

Available Make Commands

Command Description
make install Install package for production
make dev-install Install package with development dependencies
make format Format code using black and isort
make lint Run code quality checks
make test Run tests with pytest
make coverage Generate test coverage report
make clean Remove build artifacts and cache files
make build Build distribution packages
make publish Prepare package for PyPI publishing
make all Run all quality checks and tests
make help Show available commands

Project Structure

centralized_rate_limiter/
โ”œโ”€โ”€ .git/
โ”œโ”€โ”€ .gitignore
โ”œโ”€โ”€ centralized_rate_limiter/
โ”‚   โ”œโ”€โ”€ __init__.py
โ”‚   โ””โ”€โ”€ rate_limiting.py
โ”œโ”€โ”€ tests/
โ”‚   โ””โ”€โ”€ test_rate_limiting.py
โ”œโ”€โ”€ Makefile
โ”œโ”€โ”€ pyproject.toml
โ”œโ”€โ”€ README.md
โ””โ”€โ”€ LICENSE

Configuration Files

pyproject.toml

The pyproject.toml file contains all project configurations:

  • Build system configuration
  • Package metadata
  • Dependencies (both runtime and development)
  • Tool configurations:
    • pytest settings
    • coverage settings
    • black configuration
    • isort configuration

Makefile

The Makefile provides convenient commands for common development tasks. See the commands table above for available operations.

Continuous Integration

The project uses GitHub Actions for CI/CD, running the following checks on each pull request:

  • Code formatting (black, isort)
  • Linting (pylint, flake8)
  • Tests with coverage reporting
  • Package building

๐Ÿค Contributing

Please read our Contributing Guide for details on our code of conduct and the process for submitting pull requests.

๐Ÿ“œ License

This project is licensed under the Apache 2.0 License - see the LICENSE file for details.

๐Ÿ“š API Reference

RateLimitedSession

class RateLimitedSession(requests.Session):
    """A rate-limited HTTP session with built-in retry logic."""
    
    def __init__(
        self,
        requests_per_second: int = 10,
        total_retries: int = 5,
        backoff_factor: float = 0.25,
        additional_limits: Optional[List[Tuple[int, float]]] = None
    ) -> None:
        """Initialize a new rate-limited session."""

get_rate_limiter

def get_rate_limiter(
    requests_per_second: int = 10,
    total_retries: int = 5,
    backoff_factor: float = 0.25,
    additional_limits: Optional[List[Tuple[int, float]]] = None
) -> RateLimitedSession:
    """Create a new rate-limited session with specified parameters."""

๐Ÿ™ Acknowledgments

๐Ÿ“ง Contact

For questions and support, please open an issue in the GitHub repository.


Made with โค๏ธ for the Python community

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

centralized_rate_limiter-0.2.2.tar.gz (13.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

centralized_rate_limiter-0.2.2-py3-none-any.whl (11.8 kB view details)

Uploaded Python 3

File details

Details for the file centralized_rate_limiter-0.2.2.tar.gz.

File metadata

  • Download URL: centralized_rate_limiter-0.2.2.tar.gz
  • Upload date:
  • Size: 13.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.9.21

File hashes

Hashes for centralized_rate_limiter-0.2.2.tar.gz
Algorithm Hash digest
SHA256 ff3b267ba0641a0e3b60cf77fb6734c0ee0c504f0aa3fbf005352da3cf7423c4
MD5 5ae318cb2d2205a4adf36102ce64f64f
BLAKE2b-256 d42409452b955b5e458ba13b9abe318837d9be092cd19ef0577b72e32d6eea8e

See more details on using hashes here.

File details

Details for the file centralized_rate_limiter-0.2.2-py3-none-any.whl.

File metadata

File hashes

Hashes for centralized_rate_limiter-0.2.2-py3-none-any.whl
Algorithm Hash digest
SHA256 1a75f8ddeec6e1b3f0403874258dadefb1b26e5d60f61e4c9416293b6df1c6da
MD5 60f706b0556d634d96bf3e5aad133593
BLAKE2b-256 03b69ca7cd2559523055dce38205a44d7efbece4475e821590e344d90d4894bb

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page