Skip to main content
Glama
cache.py1.83 kB
"""Simple async-aware TTL cache used for 4get API responses.""" from __future__ import annotations import asyncio import time from dataclasses import dataclass from typing import Any @dataclass(slots=True) class CacheEntry: value: Any expires_at: float def expired(self, now: float | None = None) -> bool: current = time.monotonic() if now is None else now return current >= self.expires_at class TTLCache: """Lightweight cache with TTL semantics for async contexts.""" def __init__(self, ttl_seconds: float, maxsize: int) -> None: self._ttl = max(ttl_seconds, 0.0) self._maxsize = max(1, maxsize) self._entries: dict[str, CacheEntry] = {} self._lock = asyncio.Lock() async def get(self, key: str) -> Any | None: async with self._lock: entry = self._entries.get(key) if entry is None: return None if entry.expired(): self._entries.pop(key, None) return None return entry.value async def set(self, key: str, value: Any) -> None: if self._ttl == 0: return expires_at = time.monotonic() + self._ttl entry = CacheEntry(value=value, expires_at=expires_at) async with self._lock: if len(self._entries) >= self._maxsize: self._evict_one_locked() self._entries[key] = entry async def clear(self) -> None: async with self._lock: self._entries.clear() def _evict_one_locked(self) -> None: """Remove the oldest cache entry (by expiration time).""" if not self._entries: return oldest_key = min(self._entries, key=lambda key: self._entries[key].expires_at) self._entries.pop(oldest_key, None)

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/yshalsager/mcp-4get'

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