From c9f1bcd1223e4c91440b3036d9b4aa096edfa66c Mon Sep 17 00:00:00 2001 From: OG T Date: Wed, 8 Apr 2026 21:47:38 +0800 Subject: [PATCH] =?UTF-8?q?fix(api):=20service=5Fregistry=20=E5=AE=89?= =?UTF-8?q?=E5=85=A8=E9=99=8D=E7=B4=9A=20=E2=80=94=20Docker=20=E7=84=A1=20?= =?UTF-8?q?YAML=20=E6=99=82=E4=B8=8D=20crash=EF=BC=8Cfallback=20AUTO?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/api/src/services/service_registry.py | 39 ++++++++++++----------- 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/apps/api/src/services/service_registry.py b/apps/api/src/services/service_registry.py index 14279d61..fdd1b518 100644 --- a/apps/api/src/services/service_registry.py +++ b/apps/api/src/services/service_registry.py @@ -16,24 +16,23 @@ import yaml logger = structlog.get_logger(__name__) -# YAML 路徑 — 安全搜尋,相容本地開發 + Docker 容器 -# 本地: apps/api/src/services/ → parents[4] = repo root -# Docker: /app/src/services/ → parents[3] = /app → 需要往上找 ops/config -def _find_registry_path() -> Path: - """安全搜尋 service-registry.yaml,相容不同部署環境""" - candidates = [ - Path(__file__).resolve().parents[4] / "ops" / "config" / "service-registry.yaml", # 本地開發 - Path(__file__).resolve().parents[3] / "ops" / "config" / "service-registry.yaml", # Docker - Path("/app/ops/config/service-registry.yaml"), # Docker 絕對路徑 - Path(__file__).resolve().parents[2] / "ops" / "config" / "service-registry.yaml", - ] - for p in candidates: - if p.exists(): - return p - # fallback: 回傳第一個候選(會在載入時報錯,但不會 crash import) - return candidates[0] +# YAML 路徑 — 延遲載入,import 時不 crash +# Docker 容器不包含 ops/ 目錄,所以 registry 在 K8s 環境中不可用 +# 功能降級: 找不到 YAML 時 get_service_registry() 回傳空 registry +_DEFAULT_REGISTRY_PATH: Path | None = None -_DEFAULT_REGISTRY_PATH = _find_registry_path() +def _find_registry_path() -> Path | None: + """安全搜尋 service-registry.yaml,找不到回傳 None""" + current = Path(__file__).resolve().parent + for _ in range(10): + for subdir in ["ops/config", "ops/monitoring"]: + candidate = current / subdir / "service-registry.yaml" + if candidate.exists(): + return candidate + if current == current.parent: + break + current = current.parent + return None class StatefulLevel(str, Enum): @@ -64,7 +63,7 @@ class ServiceRegistryClient: """ def __init__(self, registry_path: Path | None = None) -> None: - self._path = registry_path or _DEFAULT_REGISTRY_PATH + self._path = registry_path or _find_registry_path() self._services: dict[str, ServiceInfo] = {} self._backup_policies: dict[str, Any] = {} self._multisig_config: dict[str, Any] = {} @@ -73,6 +72,10 @@ class ServiceRegistryClient: def _load(self) -> None: if self._loaded: return + if self._path is None or not self._path.exists(): + logger.warning("service_registry_not_found", path=str(self._path), fallback="all services treated as AUTO") + self._loaded = True + return try: with open(self._path) as f: data = yaml.safe_load(f)