51 lines
1.3 KiB
Python
51 lines
1.3 KiB
Python
|
|
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
|