Документирована архитектура мок-полигона от Opus (3 фазы, 12 шагов, 10 решений)

This commit is contained in:
2026-07-31 18:45:27 +04:00
parent bb15455bcb
commit bcf9f00654
+73
View File
@@ -328,3 +328,76 @@ site/
1. `mock/nubes_mock.py` — Flask-заглушка (~150 строк)
2. Интеграционный тест: сценарий `create→modify→delete` через `app_client`
3. `NUBES_MOCK=1` в `app.py` для переключения эндпоинта
---
## Архитектура мок-полигона (Опус, 2026-07-31)
### Принятые решения (10/10)
| Q | Решение | Обоснование |
|---|---------|-------------|
| Q1 | Отдельный процесс :5001 (A) | `http_client` делает реальные GET/POST — blueprint не проверит |
| Q2 | Папка `polygon/services/*.yaml` | Каждый сервис в своём файле |
| Q3 | Мин. поля (id+код+тип), остальное достраивается | 20+ параметров вручную — ад |
| Q4 | Ленивый dtFinish (A) | Без потоков, детерминированно, `MOCK_OP_DELAY=0.1` |
| Q5 | Единая стейт-машина | create→running→suspended→deleted |
| Q6 | Реальный мерж params | Иначе тест modify→проверить state.params бессмысленен |
| Q7 | Статический stateOut из YAML | Для MVP, генерация потом |
| Q8 | `/_mock/reset` | Без сброса тесты влияют друг на друга |
| Q9 | Тесты через `app_client` | Проверяет реальную связку, не только эмулятор |
| Q10 | refSvcId игнорируем в MVP | validate-cfs всегда OK |
### Критические точки интеграции (из кода)
1. **Location обязателен.** `HttpClient.post` достаёт UUID из заголовка `Location`.
Мок ОБЯЗАН отдавать `Location: ./<uuid>` на POST /instances и POST /instanceOperations.
2. **Поллинг спит 5с.** `poll_until_done` делает GET, затем `time.sleep(5)`.
При `MOCK_OP_DELAY=0` dtFinish появится на первом же GET — без задержки.
3. **Точка переключения — auth.py.** `get_client()``detect_endpoint()`.
Нужен short-circuit: при `NUBES_MOCK=1` возвращать `http://localhost:5001/api/v1/svc`
и НЕ вызывать `detect_endpoint`.
4. **validate-cfs = пустое тело.** Мок отдаёт 200 с пустым телом.
5. **state.params по коду, cfsParams по числовому id.** YAML должен связывать
`svcOperationCfsParamId` ↔ код параметра.
### План реализации (3 фазы, 12 шагов)
**Фаза 1 — MVP (create + поллинг):**
1. `polygon/defaults.py``default_for(dataType)` по типу
2. `polygon/config_loader.py` — загрузка `services/*.yaml`, достройка defaults
3. `polygon/state.py``MockState`: instances, operations, create, run, ленивый dtFinish, reset
4. `polygon/server.py` — Flask, префикс `/api/v1/svc`, Location-заголовки
5. `polygon/services/dummy.yaml` — Болванка (id параметров из HAR)
6. Интеграция в `auth.py`: short-circuit по `NUBES_MOCK`
**Фаза 2 — полный CRUD + сервисы:**
7. GET /instances/{uid} (state.params/state.out), GET /instances (пагинация)
8. GET /instanceOperations/default/{id}, GET /services, GET /services/{id}
9. `apply_effect`: modify→мерж params, delete→удаление, suspend/resume→статус
10. `/_mock/reset` + `polygon/services/postgresql.yaml`
**Фаза 3 — тесты:**
11. `tests/conftest.py` — фикстура поднятия мока + автосброс
12. `tests/test_mock_integration.py` — 5 сценариев через `app_client`
### Структура файлов
```
app-autotest/
├── site/
│ ├── api/auth.py # +short-circuit NUBES_MOCK
│ └── ...
└── polygon/
├── server.py # Flask-приложение эмулятора
├── state.py # MockState (в памяти)
├── config_loader.py # загрузка YAML + достройка defaults
├── defaults.py # default_for(dataType)
└── services/
├── dummy.yaml # Болванка
└── postgresql.yaml # PostgreSQL (stateOut: users, databases)
```