Add PCP architecture docs and TGU ops updates

Capture current PCP architecture notes, service-map prototypes, TGU operations UI/map work, local configuration updates, database helper scripts, and request/sample JSON artifacts.
This commit is contained in:
Дмитрий Соловьев
2026-05-30 14:18:19 +03:00
parent 9fca4d4051
commit c3a1a8b4a1
86 changed files with 10426 additions and 74 deletions
+266
View File
@@ -0,0 +1,266 @@
# Observatio Terrae (pcp) — карта сервисов, взаимодействие и контракты
> Базовый справочный документ для доработки системы планирования ДЗЗ.
> Составлен из исходного кода (контроллеры, Kafka listeners/publishers, HTTP-клиенты) и `config-repo`.
> Помечено явно, что **проверено по коду**, а что **требует уточнения** (`⚠`).
Стек: Kotlin + Spring Boot, Spring Cloud Config, Spring Boot Admin, Camunda 8 / Zeebe (оркестрация), Kafka (события), PostgreSQL (БД на сервис, Flyway), Helm + GitLab CI.
---
## 1. Карта сервисов — кто за что отвечает
### Доменные сервисы
| Сервис | Зона ответственности | REST base | Хранит | Kafka (in / out) | Зрелость* |
|---|---|---|---|---|---|
| **pcp-request-service** | Приём и жизненный цикл заявок на съёмку; сетка Земли (earth-grid), геопривязка ячеек, сопоставление маршрутов с заявками | `/v1/requests`, `/v1/cells`, `/v1/grid` | заявки, ячейки сетки, outbox | in: `pcp.route.georeference.v1` · out: `pcp.request.completed.v1` (outbox) | 🟢 высокая |
| **pcp-route-processing-service** | Приём «паспортов маршрутов», нормализация/геопривязка, ретрансляция дальше; собственный outbox + DLQ | `/api/route-processing` (test) | outbox маршрутов | in: `pcp.request.survey-georeference.v1` · out: `pcp.route.georeference.v1`, `pcp.route.in.v1`, DLQ | 🟢 высокая |
| **pcp-satellite-catalog-service** | Каталог КА (источник истины): спутники, группы, observation/slot-профили | `/api/satellites`, `/api/satellite-groups` | каталог КА, профили | out: `pcp.satellites` (`SatelliteDeletedEvent`) | 🟡 средняя (мало тестов) |
| **pcp-ballistics-service** | Баллистика: орбиты, ЗРВ/RVA, узлы, трассы, time-extract по TLE | `/api/satellites`, `/api/obj-view`, `/api/tle`, `/api/rva` | орбитальные данные | in: `pcp.tle` (IC/ICRV/TLE фильтры), `pcp.satellites` | 🟡 средняя |
| **tle-monitoring-service** | Подтяжка TLE (CelesTrak), мониторинг каталога | — | TLE-история | in: `pcp.satellites` · out: `pcp.tle` ⚠ | 🟡 средняя |
| **pcp-coverage-scheme-service** | Расчёт схемы покрытия (coverage scheme) | `/api/coverage-schemes` | результаты схем | in: `pcp.satellites` | 🟡 средняя |
| **slots-service** | Слоты сброса/ресурсы: расчёт, бронирование, статусы слотов | (см. контроллеры) | слоты, брони | in/out: `pcp.slots.status.v1` (`BookedSlotsStatusChangedEvent`); in: `pcp.satellites` | 🟢 высокая (лучшее покрытие тестами) |
| **pcp-complex-mission-service** | Комплексный план по тепловой карте методом слотов; снапшоты планов | `/api/satellites`, `/api/com-plan` | комплексные планы, снапшоты | in: `pcp.satellites` | 🟢 высокая |
| **pcp-mission-planing-service** | План по конкретному КА: съёмка / сброс / стирание; **хост Zeebe-воркеров** оркестрации | `/api/missions` | миссии, режимы | in: `pcp.slots.status.v1`, `pcp.route.in.v1`, `pcp.satellites` | 🔴 низкая (есть заглушки в `FlowService`) |
| **pcp-dynamic-plan-service** | Динамический/текущий план (greedy-математика, расчёт по интервалам) | `/v1/main/calcPlan` | прогоны (runs), результаты | in: `pcp.satellites` | 🟡 средняя |
| **pcp-tgu-service** | Операторская оркестрация (ТГУ/Mission Ops): окна видимости, выдача планов, решения по планам; **деплой и запуск BPMN** | `/api/plans`, `/api/platforms`, `/test/tgu` | планы КА, dedup-таблицы | in: `pcp.tgu.satellite-plan-decision.v1` · out: `pcp.tgu.visibility-windows-changed.v1` | 🟢 высокая |
| **pcp-stations-service** | Каталог наземных станций приёма | `/api/stations` | станции | — | 🟡 средняя |
| **pcp-ui-service** | BFF/агрегатор для веб-UI и 3D-глобуса (CZML/Cesium); проксирует во все сервисы | `/requests`, `/map`, `/api/*` | — (stateless) | — | 🟡 средняя |
\* Зрелость = оценка по соотношению тестов, наличию idempotency/outbox, чистоте слоёв и отсутствию заглушек (см. предыдущий разбор).
### Инфраструктурные модули
| Модуль | Роль |
|---|---|
| **spring-cloud-config-server** | Раздаёт конфигурацию из `config-repo` всем сервисам |
| **pcp-srpring-boot-admin-server** | Spring Boot Admin — мониторинг/health всех сервисов (опечатка в имени: `srpring`) |
| **pcp-tgu-ops-ui** | Плейсхолдер фронта Mission Ops (пустой, прототипы в `docs/ui-prototypes`) |
| **libs/pcp-types-lib** | Общие DTO и конверт `KafkaMessage<T>`, перечисление `PcpKafkaEvent` |
| **libs/ballistics-lib** | Общие баллистические расчёты |
---
## 2. Диаграммы взаимодействия
### 2.1. Синхронные зависимости (REST) — кто кого вызывает
Рёбра восстановлены из ключей `*-service*` base-url в `config-repo` и имён HTTP-клиентов в коде.
```mermaid
flowchart TD
UI[pcp-ui-service<br/>BFF / агрегатор]
REQ[pcp-request-service<br/>заявки + earth-grid]
CAT[pcp-satellite-catalog-service<br/>каталог КА]
BAL[pcp-ballistics-service]
CM[pcp-complex-mission-service]
MP[pcp-mission-planing-service]
SL[slots-service]
CS[pcp-coverage-scheme-service]
DP[pcp-dynamic-plan-service]
TGU[pcp-tgu-service]
ST[pcp-stations-service]
TLE[tle-monitoring-service]
UI --> REQ & CM & DP & TGU & CAT & BAL & ST & SL & MP & CS
CM --> BAL & REQ & CAT & ST & SL & CS
MP --> BAL & CM & CAT & ST
SL --> REQ & CAT
DP --> REQ & BAL & CAT
CS --> BAL & CM & CAT
TLE --> CM & CAT
TGU --> BAL
TLE -.внешний.-> CTRAK[(CelesTrak)]
TGU -.внешний.-> ORD[(ordinis.nstart.cloud<br/>классификатор платформ + external points)]
```
Наблюдения по графу:
- `pcp-satellite-catalog-service` и `pcp-ballistics-service` — самые востребованные (почти все зовут их). Кандидаты на повышенные требования к SLA/надёжности.
- `pcp-ui-service` — точка агрегации (BFF), завязан на всё.
- ⚠ Есть взаимный вызов `complex-mission ⇄ coverage-scheme` (CM зовёт CS на расчёт, CS в конфиге знает про CM) — проверить, нет ли циклической зависимости в рантайме.
### 2.2. Событийный слой (Kafka) — потоки данных
```mermaid
flowchart LR
EXT[Внешний источник / UI ⚠] -->|pcp.request.survey-georeference.v1| RP[route-processing]
RP -->|pcp.route.georeference.v1| REQ[request-service]
RP -->|pcp.route.in.v1| MP[mission-planing]
REQ -->|pcp.request.completed.v1 ⚠ потребитель| Q1{{?}}
CAT[satellite-catalog] -->|pcp.satellites / SatelliteDeletedEvent| BAL[ballistics]
CAT --> TLEM[tle-monitoring]
CAT --> SL[slots]
CAT --> MP
CAT --> CM[complex-mission]
CAT --> DP[dynamic-plan]
TLEM -->|pcp.tle| BAL
SL -->|pcp.slots.status.v1 / BookedSlotsStatusChanged| MP
SL -->|pcp.slots.status.v1| SL
MissionOps[Mission Ops / КА ⚠] -->|pcp.tgu.satellite-plan-decision.v1| TGU[tgu-service]
TGU -->|pcp.tgu.visibility-windows-changed.v1| TGU
```
### 2.3. Сквозной сценарий планирования (sequence)
Упрощённый happy-path от заявки до выдачи задания на КА.
```mermaid
sequenceDiagram
participant U as UI
participant RQ as request-service
participant RP as route-processing
participant CM as complex-mission
participant SL as slots-service
participant TGU as tgu-service (Camunda)
participant MP as mission-planing (Zeebe workers)
U->>RQ: POST заявка на съёмку
RP-->>RQ: pcp.route.georeference.v1 (геопривязанные маршруты)
RQ->>RQ: сопоставление маршрут↔заявка, RequestCompleted (outbox)
U->>CM: POST /api/com-plan/process (комплексный план)
CM->>SL: расчёт/бронирование слотов
CM->>CM: снапшот комплексного плана
U->>TGU: POST /test/tgu/plans/{id}/issue
TGU->>TGU: start BPMN createSatelliteMission
Note over TGU,MP: Zeebe job dispatch по jobType
TGU-->>MP: calculateSatelliteSurveyMissions
MP->>MP: план съёмки
TGU-->>MP: calculateSatelliteDropMissions
MP->>MP: план сброса
TGU-->>MP: sendSatellitePlan
MP-->>TGU: Message_SatellitePlanAccepted ⚠ (сейчас имитация)
MissionOps-->>TGU: pcp.tgu.satellite-plan-decision.v1 (ACCEPTED/REJECTED)
TGU->>TGU: updateAcceptedPlanSlots BPMN → updateSlotsStatus
```
---
## 3. Контракты между сервисами
### 3.1. Оркестрация Camunda 8 / Zeebe
**Деплой BPMN:** `pcp-tgu-service` через `@Deployment` при старте грузит:
`classpath:BPMN/createSatelliteMission.bpmn`, `classpath:BPMN/updateAcceptedPlanSlots.bpmn`.
**Zeebe job workers** (реализованы в `pcp-mission-planing-service/FlowService`):
| jobType | Назначение | Вход (process variables) | Выход | Примечание |
|---|---|---|---|---|
| `calculateSatelliteSurveyMissions` | План съёмки | `satellitePlanId`, `spacecraftId`, `planStartTime`, `planEndTime` | `modes: Int` | `autoComplete=false` |
| `calculateSatelliteDropMissions` | План сброса | `satellitePlanId` | `modes: Int` | — |
| `sendSatellitePlan` | Отправка плана на КА | `satellitePlanId` | — | ⚠ сейчас `Thread.sleep` + имитация подтверждения |
| `updateSlotsStatus` | Подтверждение, обновление слотов | `satellitePlanId` | `slots: List` | используется в `updateAcceptedPlanSlots` |
**Camunda message:** `Message_SatellitePlanAccepted`, `correlationKey = satellitePlanId`.
> ⚠ `schemes/pcp_v1.bpmn` — большой концептуальный процесс (шлюзы, параллельные ветки, подпроцессы), **не задеплоен** и без jobType. Реально работает только минимальный `createSatelliteMission.bpmn` (start → 3 service task → end, без обработки ошибок).
### 3.2. Kafka-топики (реестр)
Конверт по умолчанию — `KafkaMessage<T>` из `pcp-types-lib`: поля `type`, `data`, `traceId`, `correlationId`, `id`, `source`, `time`. Тип события — enum `PcpKafkaEvent`.
| Топик | Producer | Consumer(s) | Тип события / payload | Ключ |
|---|---|---|---|---|
| `pcp.satellites` | satellite-catalog | ballistics, tle-monitoring, slots, mission-planing, complex-mission, dynamic-plan | `SatelliteDeletedEvent` (`satelliteId`, `noradId`) | `satelliteId` |
| `pcp.tle` | tle-monitoring / catalog ⚠ | ballistics (фильтры IC/ICRV/TLE) | TLE / `ICPlacedEvent` / `ICRVPlacedEvent` / `ICUpdatedEvent` | ⚠ |
| `pcp.request.survey-georeference.v1` | внешний / UI ⚠ | route-processing | RoutePassport (сырой) | ⚠ |
| `pcp.request.survey-georeference-dlq.v1` | route-processing | (DLQ) | — | — |
| `pcp.route.georeference.v1` | route-processing | request-service | `RoutePassportDto` (геопривязанный) | ⚠ |
| `pcp.route.in.v1` | route-processing | mission-planing (`ModeStatusChangedEvent`) | processed route / mode-status | ⚠ |
| `pcp.request.in.v1` | request-service / UI ⚠ | ⚠ требует уточнения | `RequestPlacedEvent` | ⚠ |
| `pcp.request.completed.v1` | request-service (outbox) | ⚠ требует уточнения | RequestCompleted | `aggregateId` (UUID заявки) |
| `pcp.slots.status.v1` | slots-service | mission-planing, slots-service (self) | `BookedSlotsStatusChangedEvent` | ⚠ |
| `pcp.tgu.satellite-plan-decision.v1` | Mission Ops / КА ⚠ | tgu-service | `PlanDecisionMessage` (ACCEPTED/REJECTED, `attemptId`) | ⚠ |
| `pcp.tgu.visibility-windows-changed.v1` | tgu-service | tgu-service | `VisibilityWindowsChangedMessage` | ⚠ |
> ⚠ Реализация консьюмеров неоднородна: одни читают типизированный `KafkaMessage<T>`, другие парсят сырое дерево и ждут поле `data`; используются обе версии Jackson (2 и 3). Это первый кандидат на унификацию контракта.
### 3.3. REST-эндпоинты (контракты API по сервисам)
**request-service** (`/v1`)
```
GET /v1/requests/{id}
GET /v1/requests/{requestId}/with-cells
DELETE /v1/requests/{id}
GET /v1/cells/with-requests
GET /v1/grid/settings PUT /v1/grid/settings POST /v1/grid/rebuild
```
**satellite-catalog-service** (`/api/satellites`, `/api/satellite-groups`)
```
GET/PUT/DELETE /api/satellites/{satellite_id}
GET /api/satellites/by-norad/{norad_id}
GET/POST/PUT/DELETE /api/satellites/{satellite_id}/observation-profile
GET/POST/PUT/DELETE /api/satellites/{satellite_id}/slot-profile
POST /api/satellites/batch
GET/PUT/DELETE /api/satellite-groups/{group_id}
```
**ballistics-service** (`/api`)
```
POST /api/satellites/{satellite_id}/extract-time POST /api/satellites/{satellite_id}/clear
GET /api/satellites/{norad_id}/orbit | /asc-node | /flight-line | /rva
GET /api/satellites/orbit/availability[/{id}]
POST /api/obj-view/mpl-square | /mpl-point GET /api/obj-view/cell-coverage/{number}
POST /api/tle/parse | /api/tle/rva
```
**complex-mission-service** (`/api`)
```
POST /api/com-plan/process | /clear GET/DELETE /api/com-plan/runs/{id}
GET /api/com-plan/runs | /runs/{id}/modes | /cell-with-mars/{cell_number}
GET /api/satellites/{satellite_id}[/mission|/modes|/snapshots|/mission/statistics|/mission-for-paint]
GET /api/satellites/snapshots[/{snapshot_id}[/modes]] | /modes POST /api/satellites/prepare
```
**mission-planing-service** (`/api/missions`)
```
GET /api/missions/{mission_id}[/modes] GET /api/missions/modes/satellite
POST /api/missions/{mission_id}/drops/calculate POST /api/missions/{mission_id}/surveys/calculate
POST /api/missions/{mission_id}/confirm PUT /api/missions/survey-modes/{mode_id}/status
PUT/DELETE /api/missions/{mission_id}
```
**slots-service / coverage-scheme / dynamic-plan / stations / tgu**
```
coverage-scheme : POST /api/coverage-schemes/calculate
dynamic-plan : POST /v1/main/calcPlan ; GET /v1/main/calcPlan/runs|/{runId}[/result|/routes|/intervals]
stations : GET /api/stations[/{station_id}] ; POST /api/stations ; DELETE /api/stations/{station_id}
tgu : GET /api/plans/{spacecraftId} ; /api/platforms ;
POST /test/tgu/plans/{planId}/issue|/decision ; /spacecraft/{id}/refresh-visibility|/rebuild-plans
```
**ui-service** — BFF, агрегирует вызовы: `/requests/*`, `/map`, `/api/requests`, `/api/slots/booking/request`,
`/api/com-plan/*`, `/api/tgu-planning/*`, `/api/current-plans/*`, `/api/dynamic-plan/*`, `/api/stations/*`.
### 3.4. Внешние интеграции
| Откуда | Куда | Назначение |
|---|---|---|
| tle-monitoring-service | CelesTrak | загрузка TLE |
| tgu-service | `https://ordinis.nstart.cloud/api/v1/spacecraft/records` | классификатор платформ (фильтр `OPERATIONAL`), кэш 15m |
| tgu-service | external points API (`pcp.services.ballistics`) | внешние точки (lookahead 3 дня) |
---
## 4. Открытые вопросы для уточнения перед доработкой
Эти пункты помечены `⚠` выше — их стоит зафиксировать до изменений:
1. Producer топиков `pcp.request.survey-georeference.v1` и `pcp.request.in.v1` (внешняя система или UI?).
2. Consumer `pcp.request.completed.v1` — кто слушает завершённые заявки (предположительно complex-mission/планирование).
3. Producer `pcp.tgu.satellite-plan-decision.v1` — реальный Mission Ops/КА vs текущая имитация в `FlowService`.
4. Точные DTO payload для `pcp.tle`, `pcp.route.in.v1`, `pcp.slots.status.v1` — зафиксировать схемы.
5. Возможная циклическая зависимость `complex-mission ⇄ coverage-scheme` в рантайме.
6. Расхождение задеплоенного `createSatelliteMission.bpmn` и концептуального `schemes/pcp_v1.bpmn` — какой считать целевым.
---
*Документ описывает текущее состояние «как есть». При доработке обновлять разделы 2–3 синхронно с изменениями контроллеров, listener'ов и `config-repo`.*