from enum import Enum import logging logger = logging.getLogger(__name__) class ZoomErrorKind(str, Enum): AUTH = "auth" RATE_LIMITED = "rate_limited" TRANSIENT = "transient" PERMANENT = "permanent" NETWORK = "network" UNKNOWN = "unknown" class ZoomError(Exception): def __init__( self, message: str, kind: ZoomErrorKind = ZoomErrorKind.UNKNOWN, status_code: int | None = None, retry_after: int | None = None, ): super().__init__(message) self.kind = kind self.status_code = status_code self.retry_after = retry_after def classify_http_status(status_code: int) -> ZoomErrorKind: if status_code == 401: return ZoomErrorKind.AUTH if status_code == 429: return ZoomErrorKind.RATE_LIMITED if status_code in (500, 502, 503, 504): return ZoomErrorKind.TRANSIENT if 400 <= status_code < 500: return ZoomErrorKind.PERMANENT return ZoomErrorKind.UNKNOWN def is_retryable(kind: ZoomErrorKind) -> bool: return kind in (ZoomErrorKind.RATE_LIMITED, ZoomErrorKind.TRANSIENT, ZoomErrorKind.NETWORK) def retry_delay_ms(attempt: int, base_ms: int = 1000, max_ms: int = 30000) -> int: return min(base_ms * (2**attempt), max_ms) MAX_RETRIES = 3