from __future__ import annotations import asyncio import copy import time from live_prototype import build_live_prototype_payload from settings import Settings class PrototypePayloadCache: def __init__(self) -> None: self._payload: dict[str, object] | None = None self._expires_at = 0.0 self._lock = asyncio.Lock() async def get(self, settings: Settings) -> dict[str, object]: if settings.forgejo_cache_ttl_seconds <= 0: return copy.deepcopy(await self._build_public_payload(settings)) now = time.monotonic() if self._payload is not None and now < self._expires_at: return copy.deepcopy(self._payload) async with self._lock: now = time.monotonic() if self._payload is not None and now < self._expires_at: return copy.deepcopy(self._payload) payload = await self._build_public_payload(settings) self._payload = copy.deepcopy(payload) self._expires_at = time.monotonic() + settings.forgejo_cache_ttl_seconds return copy.deepcopy(self._payload) def invalidate(self) -> None: self._payload = None self._expires_at = 0.0 async def _build_public_payload(self, settings: Settings) -> dict[str, object]: read_token = settings.forgejo_token auth_source = "server" if read_token else "none" return await build_live_prototype_payload( settings, forgejo_token=read_token, auth_source=auth_source, session_user=None, )