Files
polygon/site/config/loader.py
T

75 lines
3.5 KiB
Python

"""
config/loader.py — загрузка сервисов и глобальные конфигурационные переменные.
Этот модуль загружает все YAML-конфиги сервисов при первом импорте и хранит их
как модульные переменные. Все routes/*.py импортируют SERVICES, OPS_INDEX, DELAY,
VERSION отсюда — без дублирования загрузки и без циклических импортов.
Переменные модуля (вычисляются ОДИН раз при старте):
VERSION — str, версия полигона (единая для app.py и root.py)
SERVICES — {service_id: service_def} все сервисы
OPS_INDEX — {svcOperationId: service_def} поиск сервиса по ID операции
DELAY — float, задержка операции из MOCK_OP_DELAY (по умолчанию 0.1)
"""
import os
import yaml
# Константы для загрузки YAML
_YAML_EXTS = (".yaml", ".yml")
_DEFAULT_SERVICES_DIR = "services"
def _load_all(services_dir=_DEFAULT_SERVICES_DIR):
"""Загружает все YAML-файлы из директории сервисов.
Возвращает кортеж (services, ops_index):
services — {service_id: {name, operations, cfsParams, stateParams, stateOut, ...}}
ops_index — {svcOperationId: service_def} для быстрого поиска «чей это opId»
"""
if not os.path.isdir(services_dir):
raise FileNotFoundError(f"Services directory not found: {services_dir}")
services = {}
ops_index = {}
# Итерируем ВСЕ .yaml/.yml — без хардкода количества сервисов
for fname in sorted(os.listdir(services_dir)):
if not fname.lower().endswith(_YAML_EXTS):
continue
path = os.path.join(services_dir, fname)
with open(path, "r", encoding="utf-8") as f:
cfg = yaml.safe_load(f)
if not cfg:
continue
svc_id = cfg["service_id"]
services[svc_id] = cfg
# Индекс: svcOperationId → service_def (нужен для поиска «чей это opId»)
for op in cfg.get("operations", []):
ops_index[op["svcOperationId"]] = cfg
return services, ops_index
# ---------------------------------------------------------------------------
# Модульные переменные — инициализируются ОДИН раз при первом импорте.
# Все routes/*.py импортируют SERVICES, OPS_INDEX, DELAY отсюда.
# ---------------------------------------------------------------------------
# Загружаем конфиги сервисов (37+ YAML из services/)
SERVICES, OPS_INDEX = _load_all()
# Задержка операции в секундах (для синхронного sleep в /run).
# Меняется на лету через POST /_mock/delay/<s> — см. mock_routes.py.
# ⛔ Импортировать ТОЛЬКО через `import config.loader as _cfg` и читать `_cfg.DELAY` —
# иначе float копируется по значению и не реагирует на изменение.
DELAY = float(os.getenv("MOCK_OP_DELAY", "0.1"))
# Версия полигона — единый источник правды для app.py и routes/root.py.
# Меняется при КАЖДОМ изменении кода.
VERSION = "0.3.0"