4.9 KiB
Opus Questions + Answers — 2026-07-31
A. Единый executor (operations/executor.py)
A1. Граница executor: до /run включительно, без поллинга.
Executor делает все шаги: POST /instances → POST /instanceOperations → send_params_terraform → /run. Возвращает {instance_uid, op_uid, display_name}. Поллинг — забота вызывающего (api_test.py: async thread, scenario.py: sync while).
A2. Ошибки: dict {ok, error, failed_step}.
Не исключения. failed_step = "instances" | "instanceOperations" | "params" | "run". Оба вызывающих конвертируют в свой формат (jsonify / RuntimeError).
A3. Трекер: да, вызывать tracker_add внутри executor для всех create. Сценарные инстансы — такие же реальные инстансы в облаке, должны быть в трекере. Единообразие.
A4. _finish_op: оставить в api_test.py.
Но вынести цикл поллинга в общий хелпер poll_until_done(client, op_uid, timeout=1800) в operations/poll.py, который используют и _finish_op (async), и run_scenario (sync).
B. Гибкие ссылки на инстансы
B5. Приоритет: да. instance_uid > instance_ref > новый create.
B6. Хранение output→uid: и в памяти, и в БД.
В памяти — словарь для быстрого резолвинга во время выполнения. В БД — scenario_runs.instance_bindings обновляется после каждого create-шага. При падении воркера видно что создалось. Но runner не зависит от БД для резолвинга (только память).
B7. Валидация: да на всё.
_validate_steps() проверяет: (a) instance_ref ссылается на output из предыдущих шагов, (b) output уникален в пределах сценария, (c) для не-create шага обязателен один из instance_ref/instance_uid.
B8. Обратная совместимость: поддерживать оба формата, без миграции. Если шаг без output/instance_ref/instance_uid → fallback на старый instance_map[service_id]. Seed dummy_test работает как есть. Новые сценарии используют новый формат.
C. Схема БД
C9. Да, без изменений схемы. Только новые опциональные ключи в JSONB-объектах шагов.
C10. Да, использовать instance_bindings. После create: bindings[output_name] = instance_uid. Сохранять в БД после каждого шага.
D. UI редактора сценариев
D11. Модальное окно на весь экран. Параметры с dataDescriptor (map-fixed) — много вложенных полей, inline в scenario-body слишком тесно.
D12. Да, вынести рендер параметров в общий модуль.
static/js/params-render.js: renderParamRow(), renderMapFixedRow(), collectParams(). Используется и в operations.js, и в scenario-form.js.
D13. Pre-fill: авто при смене операции. Показывать ВСЕ параметры с defaults, пользователь удаляет лишние или меняет значения. Кнопка «Сбросить на defaults».
D14. Символические имена в БД. {"durationMs": "5000"} — человекочитаемо, стабильно. Резолвинг в numeric ID — в runtime.
E. Оптимизация
E15. Да, вынести в api/utils.py. Обе реализации (_find_uid, _uid_from_location) унифицировать.
E16. Да, startup check. При старте: UPDATE scenario_runs SET status='TIMEOUT', error_log='worker restart' WHERE status='RUNNING' AND created_at < NOW() - INTERVAL '1 hour'. Просто, без доп. инфраструктуры.
E17. Оставить lock_check. Один сценарий за раз — безопасно. Можно ослабить позже.
E18. Не в scope. fallback на API работает, потеря stages — minor. Отдельная задача.
E19. Порядок: бэкенд → UI.
operations/executor.py+operations/poll.py+api/utils.py- Формат шагов (output/instance_ref) + валидация + резолвинг
- Минимальные правки api_test.py и scenario.py (вызов executor)
- UI редактор (модал + общий рендер параметров)