How to use custom or distributed clocks
masterIn v4, each bucket owns its time source via bucket.now(). The Limiter no longer takes a clock parameter. To ensure distributed workers agree on time, you have two options:
- Override
now()on a bucket subclass: This is the recommended approach as it keepsleakconsistent. - Inject a clock into a bucket: For buckets that support
self._clock(likeInMemoryBucketorPostgresBucket), you can assign a custom clock instance to that attribute.
Built-in clocks: MonotonicClock (default), MonotonicAsyncClock, PostgresClock, SQLiteClock.
Example: Overriding now() for Redis-based time
class RedisTimeBucket(RedisBucket):
def now(self) -> int:
seconds, microseconds = self.redis.time()
return seconds * 1000 + microseconds // 1000from pyrate_limiter import AbstractClock, InMemoryBucket, RedisBucket, Rate, Duration
class RedisClock(AbstractClock):
def __init__(self, redis):
self.redis = redis
def now(self) -> int:
seconds, microseconds = self.redis.time()
return seconds * 1000 + microseconds // 1000
# Option A — override now() (recommended)
class RedisTimeBucket(RedisBucket):
def now(self) -> int:
seconds, microseconds = self.redis.time()
return seconds * 1000 + microseconds // 1000
# Option B — inject a clock into a bucket that uses self._clock
bucket = InMemoryBucket([Rate(5, Duration.SECOND)])
bucket._clock = RedisClock(redis_client)