Initial curated ITWorx_MCP_Hub source from 368fba691ea8d23403b4d56b53b5ec670d7c5020
This commit is contained in:
commit
cb5be898ea
663 files changed
+82674
No files matched your search
@@ -0,0 +1,91 @@
|
||||
"""Read-only alias registry with bounded cache and explicit invalidation."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import threading
|
||||
import time
|
||||
from collections.abc import Iterable
|
||||
from dataclasses import dataclass
|
||||
from typing import Protocol
|
||||
from uuid import UUID
|
||||
|
||||
from .models import AliasRecord, EnvironmentName, RouterSettings
|
||||
|
||||
|
||||
class AliasStateSource(Protocol):
|
||||
def aliases(self) -> Iterable[AliasRecord]: ...
|
||||
|
||||
|
||||
class StaticAliasSource:
|
||||
"""Immutable source used by tests and bootstrap wiring; the router has no mutation API."""
|
||||
|
||||
def __init__(self, records: Iterable[AliasRecord]) -> None:
|
||||
values = tuple(records)
|
||||
identities = {(record.project_slug, record.environment) for record in values}
|
||||
if len(identities) != len(values):
|
||||
raise ValueError("duplicate stable endpoint alias")
|
||||
self._records = values
|
||||
|
||||
def aliases(self) -> tuple[AliasRecord, ...]:
|
||||
return self._records
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class _CacheEntry:
|
||||
record: AliasRecord
|
||||
expires_at: float
|
||||
|
||||
|
||||
class AliasRegistry:
|
||||
def __init__(self, source: AliasStateSource, *, settings: RouterSettings | None = None) -> None:
|
||||
self.source = source
|
||||
self.settings = settings or RouterSettings()
|
||||
self._entries: dict[tuple[str, EnvironmentName], _CacheEntry] = {}
|
||||
self._lock = threading.RLock()
|
||||
|
||||
def resolve(self, project_slug: str, environment: EnvironmentName) -> AliasRecord | None:
|
||||
key = (project_slug, environment)
|
||||
now = time.monotonic()
|
||||
with self._lock:
|
||||
cached = self._entries.get(key)
|
||||
if cached is not None and cached.expires_at > now:
|
||||
return cached.record
|
||||
found = next(
|
||||
(
|
||||
record
|
||||
for record in self.source.aliases()
|
||||
if record.alias == f"/mcp/{project_slug}/{environment}"
|
||||
),
|
||||
None,
|
||||
)
|
||||
if found is not None:
|
||||
with self._lock:
|
||||
self._entries[key] = _CacheEntry(found, now + self.settings.alias_cache_ttl_seconds)
|
||||
return found
|
||||
|
||||
def invalidate(self, *, project_slug: str | None = None, client_id: UUID | None = None) -> None:
|
||||
with self._lock:
|
||||
if project_slug is None and client_id is None:
|
||||
self._entries.clear()
|
||||
return
|
||||
keys = list(self._entries)
|
||||
for key in keys:
|
||||
entry = self._entries[key]
|
||||
project_match = project_slug is None or entry.record.project_slug == project_slug
|
||||
client_match = client_id is None or any(
|
||||
binding.client_id == client_id for binding in entry.record.bindings
|
||||
)
|
||||
if project_match and client_match:
|
||||
self._entries.pop(key, None)
|
||||
|
||||
def health(self) -> dict[str, int | str]:
|
||||
try:
|
||||
registered = len(tuple(self.source.aliases()))
|
||||
except Exception:
|
||||
registered = 0
|
||||
with self._lock:
|
||||
return {
|
||||
"status": "ready" if registered else "not-ready",
|
||||
"registered_aliases": registered,
|
||||
"cached_aliases": len(self._entries),
|
||||
}
|
||||
Reference in new issue
Block a user