Docs: перенос api-operation-stages в DOCS/ из LEGACY + правка ссылок README

This commit is contained in:
“Naeel”
2026-08-09 14:50:02 +04:00
parent a1f7617d7f
commit a95606ac0a
3 changed files with 114 additions and 87 deletions
-85
View File
@@ -1,85 +0,0 @@
# Стадии выполнения операции (stages)
## Эндпоинт
```
GET /instanceOperations/{operationUid}
```
## Поле `stages`
В ответе `instanceOperation.stages` — массив объектов-стадий. Каждая стадия:
| Поле | Тип | Описание |
|------|-----|---------|
| `instanceOperationStageUid` | UUID | UID стадии |
| `stage` | string | Название (напр. `"2. Основной процесс"`) |
| `isSuccessful` | bool/null | `true`/`false`/`null` (ещё не завершена) |
| `dtStart` | datetime | Начало |
| `dtFinish` | datetime/null | Окончание (`null` — ещё идёт) |
| `duration` | float | Секунды (пересчитывается пока идёт: `729.2`) |
| `stageMsg` | JSON-string/null | Детальные логи этапа |
## Пример
Запрос:
```bash
curl -s -H "Authorization: Bearer $TOKEN" -H "User-Agent: Mozilla/5.0" \
"https://lk-api-gateway-test.ngcloud.ru/api/v1/svc/instanceOperations/{opUid}"
```
Ответ (фрагмент):
```json
{
"instanceOperation": {
"instanceOperationUid": "a955a902-...",
"operation": "create",
"isInProgress": false,
"isSuccessful": true,
"duration": 27.89,
"stages": [
{
"instanceOperationStageUid": "f88e28c9-...",
"stage": "1. Валидация",
"isSuccessful": true,
"dtStart": "2026-07-24T15:21:57.373+0300",
"dtFinish": "2026-07-24T15:22:01.804+0300",
"duration": 4.4,
"stageMsg": "[[\"Определение ресурсной платформы\",\"...\"],...]"
},
{
"stage": "2. Основной процесс",
"isSuccessful": true,
"duration": 14.1,
"stageMsg": "[[\"Установка сервиса\",\"...\"],...]"
},
{
"stage": "3. Проверки",
"isSuccessful": true,
"duration": 0.3
},
{
"stage": "4. Хранилище секретов",
"isSuccessful": null,
"dtFinish": null,
"duration": 729.2
}
]
}
}
```
## Использование для автотестов
Для отображения прогресса в UI:
1. Отправить операцию → получить `opUid`
2. Поллинг: `GET /instanceOperations/{opUid}` каждые 2-3 секунды
3. Пока `isInProgress == true` — показывать стадии из `stages[]`
4. Когда `isInProgress == false` — проверить `isSuccessful`
`stageMsg` содержит **JSON-строку** с массивом `[[заголовок, текст], ...]`. Можно распарсить и показать пользователю.
## Открытие 2026-07-24
Обнаружено при анализе ответа API во время сессии тестирования dummy-сервиса. Ранее поле `stages` пропускалось из-за большого размера ответа.
+112
View File
@@ -0,0 +1,112 @@
# Стадии выполнения операции (stages)
Как через API и код Autotest определить, на каком этапе исполнения находится команда (операция).
## Связь с реальным кодом
| Компонент | Файл | Роль |
|-----------|------|------|
| Запуск операции | `app-autotest/site/operations/executor.py``execute_operation()` | Создаёт операцию и возвращает `op_uid` |
| Поллинг (async / sync) | `app-autotest/site/operations/poll.py``poll_until_done()` | Периодически спрашивает статус и отдаёт `stages` |
| Фоновый поллинг + кэш | `app-autotest/site/routes/api_test.py``_finish_op()`, `_op_results` | Ждёт `dtFinish`, кладёт `stages` в кэш |
| Отдача в UI | `app-autotest/site/routes/api_test.py``api_test_status()` | `GET /api/test/status/<op_uid>``stages` |
| Вывод этапов (ручной режим) | `app-autotest/site/static/js/operations.js``showStages()` | Поллинг каждые 2 сек + отрисовка |
| Вывод этапов (история) | `app-autotest/site/static/js/history.js``renderStages()` | Раскрытие строки истории по клику |
## Эндпоинты
### 1. Запуск операции (получаем `opUid`)
```
POST /api/test
```
`execute_operation()` проходит этапы запуска:
1. **CREATE**: `POST /instances``instanceUid`
2. CREATE + NON-CREATE: `POST /instanceOperations``opUid`
3. Параметры: `send_params_terraform(...)`
4. `POST /instanceOperations/{opUid}/run` → запуск
Возвращает `{ok, error, failed_step, instance_uid, op_uid, display_name}`.
При `ok=False` смотри `failed_step`: `instances` / `instanceOperations` / `params` / `run`.
### 2. Поллинг статуса (определяем этап)
```
GET /api/test/status/<op_uid>
```
Ответ — dict, ключи:
- `status``"RUNNING"` / `"OK"` / `"FAIL"`
- `done` — bool, завершена ли операция
- `stages` — список этапов
- `isInProgress`, `isSuccessful`, `duration`, `errorLog`, `displayName`
Сервер сам дергает Nubes API:
```
GET /instanceOperations/{opUid}?fields=dtFinish,isSuccessful,errorLog,isInProgress,duration,stages
```
### 3. Фоновый поллинг (для сценариев/сохранения)
`poll_until_done()` поллит тот же эндпоинт и возвращает:
```python
{status, is_successful, error_log, stages, duration, svc}
```
где `status ∈ {"OK", "FAIL", "TIMEOUT"}`.
## Как определить текущий этап
Поле `stages` — массив объектов-стадий. Каждая стадия:
| Поле | Тип | Описание |
|------|-----|---------|
| `instanceOperationStageUid` | UUID | UID стадии |
| `stage` | string | Название (напр. `"1. Валидация"`) |
| `isSuccessful` | bool/null | `true`/`false`/`null` (ещё не завершена) |
| `dtStart` | datetime | Начало этапа |
| `dtFinish` | datetime/null | Окончание (`null` — ещё идёт) |
| `duration` | float | Секунды (пересчитывается, пока идёт) |
| `stageMsg` | JSON-string/null | Детальные логи этапа |
**Правило определения текущего этапа:**
- `dtFinish == null` (или `isSuccessful == null`) → этап **сейчас выполняется** — это текущий этап команды.
- `dtFinish != null` → этап завершён (`isSuccessful == true` → ✅, `false` → ❌).
- Идёшь по массиву по порядку: до первого `dtFinish == null` — уже прошли, первый с `null` — текущий, дальше — ещё не начались.
**Завершение операции:** смотри `done` / `isInProgress`. Когда `done == true``status` принимает `OK`/`FAIL`. При `FAIL` текст ошибки в `errorLog` / `error_log`.
## Пример ответа
```json
{
"status": "RUNNING",
"done": false,
"stages": [
{ "stage": "1. Валидация", "isSuccessful": true, "dtFinish": "2026-07-24T15:22:01.804+0300", "duration": 4.4 },
{ "stage": "2. Основной процесс", "isSuccessful": null, "dtFinish": null, "duration": 14.1 },
{ "stage": "3. Проверки", "isSuccessful": null, "dtFinish": null }
]
}
```
Здесь: этап 1 завершён ✅, этап 2 — **текущий** (идёт), этап 3 — ещё не начался.
## Вывод этапов в UI
### Ручной режим (`operations.js` → `showStages()`)
- Поллинг: `setInterval` каждые **2 секунды**`GET /api/test/status/{opUid}`
- `showStages(sd.stages)` рендерит этапы в последний `.stages-box`:
- иконка: `✅` (завершён успешно) / `❌` (завершён с ошибкой) / `⏳` (идёт)
- название `stage` + длительность `duration`
- `stopPoll()` после завершения; при 5 ошибках подряд поллинга → `TIMEOUT`
### История (`history.js` → `renderStages()`)
- `GET /api/history` → записи, у каждой поле `stages`
- по клику на строку раскрываются этапы (`stages` сохранены в БД `runs`, колонка `stages JSONB`)
## Примечание
`stageMsg` содержит **JSON-строку** с массивом `[[заголовок, текст], ...]` — можно распарсить и показать детальные логи этапа.
+2 -2
View File
@@ -4,8 +4,8 @@
## Документация API
- [Обращение к API облака](DOCS/api-access.md) — эндпоинты, curl-примеры
- [Полный поток CREATE](DOCS/api-create-flow.md) — схема, параметры, все ошибки
- [Обращение к API облака](DOCS/LEGACY/api-access.md) — эндпоинты, curl-примеры
- [Полный поток CREATE](DOCS/LEGACY/api-create-flow.md) — схема, параметры, все ошибки
- [Стадии выполнения операций](DOCS/api-operation-stages.md) — `stages[]` в ответе API
## Структура