""" routes/run.py — запуск операции. Blueprint "run" с префиксом /api/v1/svc. POST /instanceOperations//run — выполнить операцию. Вынесен в отдельный файл потому что логика run критична и специфична: синхронный sleep, вызов state_machine.apply_effect, простановка dtFinish. """ import time from flask import Blueprint, jsonify import mock_state import state_machine from config.loader import SERVICES, DELAY from utils.now import now as _now bp = Blueprint("run", __name__, url_prefix="/api/v1/svc") @bp.route("/instanceOperations//run", methods=["POST"]) def run_operation(uid): """POST /instanceOperations/{uid}/run — выполнить операцию. Алгоритм (синхронный, без потоков): 1. Проверить что операция существует (→ 404 если нет) 2. Записать dtStart = now() 3. sleep(DELAY) — эмуляция времени выполнения 4. Вызвать state_machine.apply_effect() — мутировать состояние инстанса 5. Записать dtFinish = now(), isSuccessful = True После этого GET /instanceOperations/{uid} вернёт dtFinish, и poll_until_done() в app-autotest завершит поллинг. ⛔ Нет защиты от повторного run — если вызвать дважды, dtStart перезапишется и эффект применится повторно. Для тестовых целей (MOCK_OP_DELAY ≤ 0.5с) вероятность минимальна. Возвращает {"ok": True} — формат как в реальном Nubes API. """ op = mock_state.state.get_operation(uid) if not op: return jsonify({"error": "operation not found"}), 404 # Фиксируем время старта op["dtStart"] = _now() # Эмулируем задержку выполнения (по умолчанию 0.1с) if DELAY > 0: time.sleep(DELAY) # Применить эффект операции к состоянию инстанса # (create → running+params, delete → удалить, modify → мерж params, ...) state_machine.apply_effect(uid, mock_state.state, SERVICES) # Фиксируем время завершения — операция выполнена успешно op["dtFinish"] = _now() op["isSuccessful"] = True return jsonify({"ok": True})