"""In-process rate limiting utilities for the Borealis Engine.""" from __future__ import annotations import time from collections import deque from dataclasses import dataclass from threading import Lock from typing import Deque, Dict __all__ = ["RateLimitDecision", "SlidingWindowRateLimiter"] @dataclass(frozen=True, slots=True) class RateLimitDecision: """Result of a rate limit check.""" allowed: bool retry_after: float class SlidingWindowRateLimiter: """Tiny in-memory sliding window limiter suitable for single-process use.""" def __init__(self) -> None: self._buckets: Dict[str, Deque[float]] = {} self._lock = Lock() def check(self, key: str, limit: int, window_seconds: float) -> RateLimitDecision: now = time.monotonic() with self._lock: bucket = self._buckets.get(key) if bucket is None: bucket = deque() self._buckets[key] = bucket while bucket and now - bucket[0] > window_seconds: bucket.popleft() if len(bucket) >= limit: retry_after = max(0.0, window_seconds - (now - bucket[0])) return RateLimitDecision(False, retry_after) bucket.append(now) return RateLimitDecision(True, 0.0)