# Change Log All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). ## [4.0.0] Fourth major release with significant API simplification and breaking changes. ### Breaking Changes #### Exceptions Removed - `BucketFullException` and `LimiterDelayException` have been removed - Rate limiting now uses blocking behavior instead of exception-based flow control #### Limiter Constructor Simplified - Removed `clock` parameter - each bucket now manages its own clock via `bucket.now()` - Removed `raise_when_fail` parameter - no exceptions are raised - Removed `max_delay` parameter - blocking is now controlled per-call - Removed `retry_until_max_delay` parameter - Added `buffer_ms` parameter (default 50ms) for clock drift tolerance #### Clock Changes - `TimeClock` removed - use `MonotonicClock` instead - `SQLiteClock` removed - buckets now manage their own time - `TimeAsyncClock` renamed to `MonotonicAsyncClock` - Clock is no longer passed to Limiter; buckets have built-in `now()` method #### try_acquire API Changes - New signature: `try_acquire(name="pyrate", weight=1, blocking=True, timeout=-1)` - `blocking=True` (default): blocks until permit is acquired - `blocking=False`: returns `False` immediately if bucket is full - Added `try_acquire_async()` for proper async acquisition with asyncio.Lock #### Decorator API Changes - Old: `limiter.as_decorator()(mapping_func)(target_func)` where mapping returns `(name, weight)` - New: `limiter.as_decorator(name="...", weight=...)(target_func)` with direct parameters #### BucketFactory Changes - `schedule_leak(bucket, clock)` now `schedule_leak(bucket)` - no clock parameter - `create(clock, bucket_class, ...)` now `create(bucket_class, ...)` - no clock parameter ### New Features - Context manager support: `with Limiter(...) as limiter:` and `with bucket:` - `limiter.close()` method for resource cleanup - `limiter_factory` module with convenience functions: - `create_sqlite_limiter()` - `create_inmemory_limiter()` - `init_global_limiter()` - `MultiprocessBucket` for multiprocessing environments - Web request helpers in `pyrate_limiter.extras`: - `aiohttp_limiter.RateLimitedSession` - `httpx_limiter.RateLimiterTransport` / `AsyncRateLimiterTransport` - `requests_limiter.RateLimitedRequestsSession` - Time is now monotonic by default (`monotonic_ns()`) - `buffer_ms` configurable per-Limiter (default 50ms) ### Improvements - Migrated from Poetry to UV for builds - Switched from Bitnami to official Redis/Postgres Docker images - Pre-commit switched to Ruff - Improved multiprocessing support with proper locking - Better asyncio support with thread-local async locks ## [3.9.0] * Introduce MultiprocessBucket * Update documentation to include MultiprocessBucket * Add delay configure * Simplify lock interface for SQLFileLock & MultiprocessBucket ## [3.8.1] * Keep Retrying until Max Delay Has Expired * Postgres performance turning * Fix cursor leaks on SQLiteBucket ## [3.8.0] * Add FileLock option for SQLiteBucket ## [3.7.1] * Update package metadata and local dev config to support python 3.13 ## [3.7.0] * Add method to remove bucket ## [3.6.2] * Fix table creation for SQLiteBucket ## [3.6.1] * Support creating/getting bucket asynchronously ## [3.6.0] * Use psycopg3 for PostgresBucket ## [3.5.1] * Fix dependencies for "all" package extra ## [3.5.0] * Add PostgresBucket backend ## [3.4.1] * Fix: unnecessary warning during async check ## [3.4.0] * Improved in-memory-bucket performance ## [3.3.0] * Fix background task for leaking ## [3.2.1] - 2024-02-13 * Fix Redis CROSSSLOT Keys following issue [#126](https://github.com/vutran1710/PyrateLimiter/issues/126) ## [3.1.1] - 2024-01-02 * Fix broken SqliteBucket following issue [#132](https://github.com/vutran1710/PyrateLimiter/issues/132) ## [3.1.0] - 2023-08-28 * Allow to pass rates directly to Limiter to use default ImMemoryBucket with Limiter * Allow to pass *Duration* to `max_delay` argument of Limiter ## [3.0.2] - 2023-08-28 * Critical bug fix: importing redis fail crashing apps ## [3.0.0] - 2023-08-28 Third major release with API breaking changes: - Drop python 3.7 (only python ^3.8) - Bucket must be initialized before passing to Limiter - Auto leaking (provided by BucketFactory) - Decorator API changes - Limiter workable with both async/sync out-of-the-box - Async RedisBucket built-in - Contextmanager not available yet ## [2.10.0] - 2023-02-26 ### Updates * Add change log to sdist * Improve test coverage * Force check some bucket-keyword arguments ## [2.9.1] - 2023-02-26 ### Fixed * Fix unit test to make test results stable * Fix remaining-time calculation using exact 3 decimals only * Increase test intesity to ensure correctness ## [2.8.5] - TBD ### Fixed * Fix SQLite OperationalError when getting more items than SQLite variable limit ## [2.8.4] - 2022-11-23 ### Fixed * Build both `wheel` and `sdist` on publish ## [2.8.3] - 2022-10-17 ### Added * Add option to expire redis key when using RedisBucket ## [2.8.2] - 2022-09-24 ### Removed * Python 3.6 support ## [2.8.1] - 2022-04-11 ### Added * Add Sphinx config * Add documentation site: https://pyrate-limiter.readthedocs.io * Add some missing type hints * Add package metadata to indicate PEP-561 compliance ## [2.8.0] - 2022-04-10 ### Added * Add `flush()` method to all bucket classes ## [2.7.0] - 2022-04-06 ### Added * Add `FileLockSQliteBucket` for a SQLite backend with file-based locking * Add optional backend dependencies to package metadata ## [2.6.3] - 2022-04-05 ### Fixed * Make SQLite bucket thread-safe and multiprocess-safe ## [2.6.2] - 2022-03-30 ### Fixed * Remove development scripts from package published on PyPI ### Added * Add `nox` to run development scripts ## [2.6.1] - 2022-03-30 ### Updated * Replace all formatting/linting tools with *pre-commit* ## [2.6.0] - 2021-12-08 ### Added * Add `SQliteBucket` to persist rate limit data in a SQLite database ## [2.5.0] - 2021-12-08 ### Added * Custom time source ## [2.4.6] - 2021-09-30 * Add `RedisClusterBucket` to support using `PyrateLimiter` with `redis-py-cluster` * Update README, add Table of Content ## [2.3.6] - 2021-09-23 * Run CI tests for all supported python versions * Fix issue with deployments on Travis CI ## [2.3.5] - 2021-09-22 ### Added * Use `time.monotonic()` instead of `time.time()` * Support for floating point rate-limiting delays (more granular than 1 second) ## [2.3.4] - 2021-06-01 ### Fixed * Bucket group initialization ## [2.3.3] - 2021-05-08 ### Added * Support for python 3.6 ## [2.3.2] - 2021-05-06 ### Fixed * Incorrect type hint ## [2.3.1] - 2021-04-26 ### Added * LICENSE file to be included in PyPI package ### Fixed * Incorrect delay time when using using `Limiter.ratelimit()` with `delay=True` ## [2.3.0] - 2021-03-01 ### Added * Support for using `Limiter.ratelimit()` as a contextmanager or async contextmanager * Separate `LimitContextDecorator` class to handle `Limiter.ratelimit()` behavior * Package published on conda-forge ## [2.2.2] - 2021-03-03 ### Changed * Internal: Reduce cognitive complexity ## [2.2.1] - 2021-03-02 ### Fixed * Incorrect check log against time-window ## [2.2.0] - 2021-02-26 ### Added * `Limiter.ratelimit()` method, an async-compatible decorator that optionally adds rate-limiting delays ## [2.1.0] - 2021-02-21 ## [2.0.3] - 2020-06-01 ## [2.0.2] - 2020-06-01 ## [2.0.1] - 2020-06-01 ## [2.0.0] - 2019-12-29 ## [1.1.0] - 2019-12-17 ### Removed - Code duplication ### Added - Thread lock for Bucket's state modification in case of Multi-threading - Html Cover Report ### Fixed - LocalBucket's default init value being mutated - Typos. A lot of friggin' typos.