first
This commit is contained in:
@@ -0,0 +1,51 @@
|
||||
"""In-memory cache OAuth Bearer tokenů PPL CPL API.
|
||||
|
||||
PPL vydá max. 12 tokenů za minutu a token platí 30 minut — generovat token
|
||||
per-request nelze. Cache je klíčovaná SHA-256 hashem přihlašovacích údajů
|
||||
(samotné údaje se neukládají) a token se obnovuje s předstihem před expirací.
|
||||
|
||||
Per-key asyncio.Lock brání souběžnému vyžádání tokenu pro stejné údaje
|
||||
(thundering herd při paralelních requestech).
|
||||
"""
|
||||
import asyncio
|
||||
import time
|
||||
|
||||
from .config import TOKEN_REFRESH_MARGIN_SECONDS
|
||||
|
||||
# cache_key -> (access_token, expires_at_monotonic)
|
||||
_tokens: dict[str, tuple[str, float]] = {}
|
||||
_locks: dict[str, asyncio.Lock] = {}
|
||||
|
||||
|
||||
def _lock_for(cache_key: str) -> asyncio.Lock:
|
||||
lock = _locks.get(cache_key)
|
||||
if lock is None:
|
||||
lock = asyncio.Lock()
|
||||
_locks[cache_key] = lock
|
||||
return lock
|
||||
|
||||
|
||||
def get_cached(cache_key: str) -> str | None:
|
||||
entry = _tokens.get(cache_key)
|
||||
if entry is None:
|
||||
return None
|
||||
token, expires_at = entry
|
||||
if time.monotonic() >= expires_at:
|
||||
_tokens.pop(cache_key, None)
|
||||
return None
|
||||
return token
|
||||
|
||||
|
||||
def store(cache_key: str, token: str, expires_in_seconds: float) -> None:
|
||||
expires_at = time.monotonic() + max(
|
||||
expires_in_seconds - TOKEN_REFRESH_MARGIN_SECONDS, 30.0
|
||||
)
|
||||
_tokens[cache_key] = (token, expires_at)
|
||||
|
||||
|
||||
def invalidate(cache_key: str) -> None:
|
||||
_tokens.pop(cache_key, None)
|
||||
|
||||
|
||||
async def acquire_lock(cache_key: str) -> asyncio.Lock:
|
||||
return _lock_for(cache_key)
|
||||
Reference in New Issue
Block a user