""" Redis sliding window rate limiter. """ import time from redis.asyncio import Redis async def is_rate_limited( redis: Redis, key: str, limit: int, window_seconds: int = 60, ) -> tuple[bool, int]: """ Returns (is_limited, requests_remaining). Uses a sorted set with timestamps as scores for sliding window. """ now = time.time() window_start = now - window_seconds pipe = redis.pipeline() pipe.zremrangebyscore(key, 0, window_start) pipe.zadd(key, {str(now): now}) pipe.zcard(key) pipe.expire(key, window_seconds + 1) results = await pipe.execute() count = results[2] remaining = max(0, limit - count) return count > limit, remaining