Redis Timers is a Python library that provides a robust framework for managing timed events using Redis as the backend.
It allows you to schedule timers that trigger handlers at specific times, with payloads automatically validated using Pydantic schemas.
- Schedule timers with custom payloads
- Automatic payload validation using Pydantic
- Distributed lock mechanism to prevent duplicate processing
- Topic-based routing for timer handlers
- Automatic cleanup of processed timers
- Built with asyncio for high performance
π¦ PyPi
π License
pip install redis-timersimport asyncio
import datetime
from redis import asyncio as aioredis
from pydantic import BaseModel
from redis_timers import Timers, Router
# Define your payload schema
class MyPayload(BaseModel):
message: str
count: int
# Create a router and register handlers
router = Router()
@router.handler(topic="my_topic", schema=MyPayload)
async def my_timer_handler(data: MyPayload, context: dict):
print(f"Timer triggered: {data.message} (count: {data.count})")
# Initialize Redis client
redis_client = aioredis.Redis.from_url("redis://localhost:6379", decode_responses=True)
# Initialize timers
timers = Timers(redis_client=redis_client, context={"app_name": "my_app"})
timers.include_router(router)
# Schedule a timer
async def schedule_timer():
payload = MyPayload(message="Hello, World!", count=42)
await timers.set_timer(
topic="my_topic",
timer_id="unique_timer_id",
payload=payload,
activation_period=datetime.timedelta(minutes=5)
)
# Run the timer processing loop
async def main():
# Schedule a timer
await schedule_timer()
# Process timers continuously
await timers.run_forever()
if __name__ == "__main__":
asyncio.run(main())The Timers class is the main interface for managing timed events. It connects to Redis and handles the scheduling, execution, and cleanup of timers.
The Router class is used to register timer handlers. Handlers are functions that get executed when a timer expires.
Handlers are async functions decorated with @router.handler() that process timer events. Each handler is associated with a topic and a Pydantic schema for payload validation.
Payloads are Pydantic models that contain the data associated with a timer. They are automatically validated when timers are processed.
Initialize a Timers instance.
redis_client: An async Redis client instancecontext: A dictionary of context data passed to handlers
Include a router with its handlers.
Include multiple routers.
Schedule a timer.
topic: The topic associated with the timer handlertimer_id: A unique identifier for the timerpayload: A Pydantic model instance containing the timer dataactivation_period: A timedelta specifying when the timer should trigger
Remove a scheduled timer.
Process all timers that are ready to be triggered.
Continuously process timers in a loop.
Create a new router instance.
Decorator for registering timer handlers.
topic: The topic to associate with this handlerschema: The Pydantic model class for payload validation
Redis Timers can be configured using environment variables:
TIMERS_TIMELINE_KEY: Redis key for the sorted set storing timer timestamps (default: "timers_timeline")TIMERS_PAYLOADS_KEY: Redis key for the hash storing timer payloads (default: "timers_payloads")TIMERS_HANDLING_SLEEP: Base sleep time between timer processing cycles (default: 0.05 seconds)TIMERS_HANDLING_JITTER_MIN_VALUE: Minimum jitter multiplier (default: 0.5)TIMERS_HANDLING_JITTER_MAX_VALUE: Maximum jitter multiplier (default: 2.0)TIMERS_SEPARATOR: Separator used between topic and timer ID (default: "--")
-
Timer Scheduling: When you call
set_timer(), Redis Timers stores:- The timer's activation timestamp in a Redis sorted set (
timers_timeline) - The timer's payload as JSON in a Redis hash (
timers_payloads) - The timer key is constructed as
{topic}{separator}{timer_id}
- The timer's activation timestamp in a Redis sorted set (
-
Timer Processing: The
run_forever()method continuously:- Checks for timers that should be triggered (current timestamp >= activation timestamp)
- Acquires a distributed lock to prevent duplicate processing
- Validates the payload using the registered Pydantic schema
- Calls the appropriate handler function
- Removes the processed timer from Redis
-
Distributed Locking: Redis Timers uses Redis locks to ensure that:
- The same timer isn't processed multiple times in distributed environments
- Concurrent modifications to the same timer are prevented
- Python 3.13+
- Redis server
- Dependencies:
pydantic,redis