Skip to main content
Glama
api_cache.py2.74 kB
import asyncio import logging from datetime import datetime, timedelta, timezone from typing import Any, Awaitable, Callable, Dict, Optional, Tuple CACHE_TTL_SECONDS = 86400 # 24 Hours # Simple in-memory async cache for successful results, with TTL class APICache: def __init__(self, ttl_seconds: int = CACHE_TTL_SECONDS): self._cache: Dict[ str, Tuple[Tuple[dict[str, Any], dict[str, dict[str, Any]]], datetime] ] = {} self._locks: Dict[str, asyncio.Lock] = {} self._ttl = timedelta(seconds=ttl_seconds) self._logger = logging.getLogger(__name__) def _key(self, workflow_id: str) -> str: return workflow_id def _now(self) -> datetime: # Use UTC for consistency return datetime.now(timezone.utc) async def get_or_set( self, workflow_id: str, fetcher: Callable[ [], Awaitable[Optional[Tuple[dict[str, Any], dict[str, dict[str, Any]]]]] ], ) -> Optional[Tuple[dict[str, Any], dict[str, dict[str, Any]]]]: key = self._key(workflow_id) now = self._now() if key in self._cache: value, ts = self._cache[key] if now - ts < self._ttl: self._logger.debug(f"Cache hit for key={key} (age={(now - ts).total_seconds()}s)") return value else: self._logger.debug( f"Cache expired for key={key} (age={(now - ts).total_seconds()}s), evicting entry" ) del self._cache[key] else: self._logger.debug(f"Cache miss for key={key}") # Prevent race conditions for the same key lock = self._locks.setdefault(key, asyncio.Lock()) async with lock: if key in self._cache: value, ts = self._cache[key] if now - ts < self._ttl: self._logger.debug( f"Cache hit for key={key} (age={(now - ts).total_seconds()}s) [post-lock]" ) return value else: self._logger.debug( f"Cache expired for key={key} (age={(now - ts).total_seconds()}s) [post-lock], evicting entry" ) del self._cache[key] self._logger.debug(f"Fetching value for key={key}") result = await fetcher() if result is not None: self._logger.debug(f"Caching value for key={key}") self._cache[key] = (result, now) else: self._logger.debug(f"Fetcher returned None for key={key}, not caching") return result api_cache = APICache()

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/jentic/jentic-tools'

If you have feedback or need assistance with the MCP directory API, please join our Discord server