v0.5.0: 3 стенда — изоляция состояния, WSGI middleware, OpenAPI server selector, POLYGON_STANDS env

- loader.py: STANDS dict, get_services/get_ops_index per stand, POLYGON_STANDS env
- mock_state.py: get_state(stand_id) — ленивая инициализация
- app.py: StandMiddleware — перезапись PATH_INFO до Flask-роутинга
- Все роуты: LocalProxy(state), LocalProxy(SERVICES/OPS_INDEX) через g.stand_id
- openapi.py: _build_servers() — по одному серверу на стенд
- services/stand{1,2,3}/ — 37 YAML на стенд из STANDS/dev и STANDS/test
- tests/test_api.py: +4 multi-stand теста (изоляция, fail-next, OpenAPI servers)
- Обратная совместимость: /api/v1/svc/... → стенд по умолчанию
This commit is contained in:
2026-08-01 20:10:19 +04:00
parent 11f98738d0
commit 58d54f2a95
122 changed files with 25223 additions and 76 deletions
+7 -3
View File
@@ -10,13 +10,17 @@ Blueprint "run" с префиксом /api/v1/svc.
import time
from flask import Blueprint, jsonify
from flask import Blueprint, g, jsonify
from werkzeug.local import LocalProxy
import mock_state
import state_machine
import config.loader as _cfg
from utils.now import now as _now
state = LocalProxy(lambda: mock_state.get_state(g.stand_id))
SERVICES = LocalProxy(lambda: _cfg.get_services(g.stand_id))
bp = Blueprint("run", __name__, url_prefix="/api/v1/svc")
@@ -37,7 +41,7 @@ def run_operation(uid):
Возвращает {"ok": True} — формат как в реальном Nubes API.
Повторный вызов → 409 (operation already completed).
"""
op = mock_state.state.get_operation(uid)
op = state.get_operation(uid)
if not op:
return jsonify({"error": "operation not found"}), 404
@@ -55,7 +59,7 @@ def run_operation(uid):
time.sleep(_cfg.DELAY)
# Проверка /_mock/fail-next — симуляция падения операции
st = mock_state.state
st = state
if st.fail_next:
st.fail_next = False # one-shot: сбросить после использования
op["dtFinish"] = _now()