Files
dc-observatio/docs/architect/PCP_SERVICE_INTERACTIONS.md
T
Дмитрий Соловьев c1259c3105 pcp-request-service: аудит-фиксы RS1/RS3/RS6/RS7
RS1 (#29): планировщик истечения заявок — RequestExpiryService
(@Scheduled + FOR UPDATE SKIP LOCKED, мультиинстанс-safe), refreshStatus
вызывается и при создании заявки.
RS7 (#35): единый топик pcp.request.status.v1 → geoportal (COMPLETED/EXPIRED
в payload), замена orphan pcp.request.completed.v1; эмиссия из matching и
expiry через тот же outbox; backoff/next_attempt_at/cap для outbox FAILED.
RS3 (#31): DefaultErrorHandler + DeadLetterPublishingRecoverer
(DLQ pcp.route.georeference-dlq.v1), bounded retry, контрактные ошибки в DLQ.
RS6 (#34): проброс coverageRequiredPercent из API, разведение терминов
покрытие/важность.

Доки: бэклог, аудит сервиса заданий, карты взаимодействий.
RS2 (#30) отложено до #28, RS5 (#33) — до роста требований к точности.
2026-06-06 23:47:19 +03:00

225 lines
17 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Карта взаимодействий сервисов PCP
> Составлено по исходникам (`services/*/src/main`) и конфигам (`config-repo/`).
> Три канала интеграции: **Kafka** (события), **HTTP/REST** (синхронные запросы), **Camunda 8 / Zeebe** (оркестрация процессов).
> Имена топиков и адреса сервисов берутся из Spring Cloud Config (`config-repo/*.yaml`,
> общая карта адресов — `application-dev.yaml` / `application-local.yaml`, ключи `pcp.services.*`).
## Содержание
1. [Перечень сервисов и порты](#1-перечень-сервисов-и-порты)
2. [Kafka — карта топиков и событий](#2-kafka--карта-топиков-и-событий)
3. [HTTP/REST — карта вызовов между сервисами](#3-httprest--карта-вызовов-между-сервисами)
4. [Camunda — процессы и воркеры](#4-camunda--процессы-и-воркеры)
---
## 1. Перечень сервисов и порты
Локальные порты — из `config-repo/application-local.yaml` (`pcp.ports.*`). В dev/docker все слушают `8080`.
| Сервис | Локальный порт | Роль |
|---|---|---|
| `spring-cloud-config-server` | 8888 | раздача конфигов |
| `pcp-srpring-boot-admin-server` | (admin) | мониторинг Spring Boot Admin |
| `tle-monitoring-service` | 7001 | загрузка/раздача TLE (CelesTrak) |
| `pcp-complex-mission-service` | 7002 | комплексные планы/миссии, режимы съёмки КА |
| `pcp-ballistics-service` | 7003 | баллистика, расчёт НУ/витков/трасс (он же `ic-service`) |
| `pcp-request-service` | 7005 | заявки, маршруты-привязки, outbox |
| `slots-service` | 7006 | слоты, бронирования, расчёт покрытия |
| `pcp-ui-service` | 7008 | BFF/агрегатор для старого UI |
| `pcp-stations-service` | 7009 | каталог наземных станций |
| `pcp-mission-planing-service` | 7010 | планирование миссий + **Camunda job-воркеры** |
| `pcp-tgu-service` | 7011 | ТГУ: выдача планов, **запуск Camunda-процессов** |
| `pcp-coverage-scheme-service` | 7012 | расчёт схем покрытия |
| `pcp-satellite-catalog-service` | 7013 | каталог КА |
| `pcp-dynamic-plan-service` | 7014 | динамические/комплексные планы (calcPlan) |
| `pcp-route-processing-service` | — | обработка маршрутных паспортов |
`pcp-tgu-ops-ui` — фронтенд (Vite), ходит в микросервисы напрямую через прокси, в этой карте не участвует как backend.
---
## 2. Kafka — карта топиков и событий
Событие — JSON-конверт `KafkaMessage` с заголовком `type` (значения из `PcpKafkaEvent`).
Консьюмеры фильтруют по этому заголовку.
### Топики
| Топик | Продюсер(ы) | Консьюмер(ы) | Событие / назначение |
|---|---|---|---|
| `pcp.tle` *(default-topic)* | `tle-monitoring-service` (TLE); `slots-service` (`ICRVPlacedEvent`) | `pcp-ballistics-service` (фильтры `placedIcFilter`, `updatedIcFilter`, `placedIcRvFilter`) | общий «шина TLE / НУ-РВ»: новые TLE и заложенные начальные условия |
| `pcp.satellites` | `pcp-satellite-catalog-service` (`SatelliteDeletedEvent`) | `tle-monitoring`, `slots-service`, `pcp-complex-mission-service`, `pcp-dynamic-plan-service`, `pcp-ballistics-service`, `pcp-mission-planing-service` | удаление КА (fan-out для очистки производных данных) |
| `pcp.slots.status.v1` | `pcp-mission-planing-service` (`BookedSlotsStatusChangedEvent`) | `slots-service` (`BookedSlotsKafkaListener`) | смена статуса забронированных слотов (lifecycle Kafka-first) |
| `pcp.route.in.v1` | `pcp-route-processing-service` (`processed-route`) | `pcp-mission-planing-service` (`ModeStatusChangedKafkaListener`, `ModeStatusChangedEvent`) | обработанный маршрут → смена статуса режима съёмки |
| `pcp.route.georeference.v1` | `pcp-route-processing-service` (`route-georeference`) | `pcp-request-service` (`RequestKafkaListener.consumeRoute`) | геопривязка маршрута к заявке |
| `pcp.request.survey-georeference.v1` | (инжект `RouteProcessingTestController` / внешний источник) | `pcp-route-processing-service` (`RoutePassportMessageListener`, вход) | входной маршрутный паспорт на обработку |
| `pcp.request.survey-georeference-dlq.v1` | `pcp-route-processing-service` (DLQ) | — | dead-letter для входных паспортов |
| `pcp.request.status.v1` | `pcp-request-service` (`OutboxPublisherService`, outbox) | **geoportal** (внешний, в репо нет) | терминальный статус заявки `COMPLETED`/`EXPIRED` (`REQUEST_TERMINAL_STATUS`) |
| `pcp.request.in.v1` | — | *(объявлен в конфиге `pcp-request-service`, активного слушателя нет)* | входящие заявки (legacy/зарезервировано) |
### Поток данных (упрощённо)
```
CelesTrak ──HTTP──> tle-monitoring ──pcp.tle(TLE)──────────────> ballistics
slots-service ─────pcp.tle(ICRVPlacedEvent)───────────────────> ballistics
satellite-catalog ──pcp.satellites(SatelliteDeletedEvent)──┬──> tle-monitoring
├──> slots-service
├──> complex-mission
├──> dynamic-plan
├──> ballistics
└──> mission-planing
route-processing ──pcp.route.in.v1──────> mission-planing (ModeStatusChanged)
route-processing ──pcp.route.georeference.v1──> request-service
(вход) pcp.request.survey-georeference.v1 ──> route-processing
mission-planing ──pcp.slots.status.v1(BookedSlots)──────> slots-service
request-service ──pcp.request.status.v1 (outbox)────────> geoportal (внешний)
```
### ТГУ-топики (`pcp.tgu.*`)
`pcp-tgu-service` объявляет консьюмеры на свои топики (`config-repo/pcp-tgu-service.yaml`, блок `topics:`).
Продюсеры этих событий — внешняя система СПО УОГ / тестовые эндпоинты; внутри репозитория стабильных продюсеров нет.
| Топик | Консьюмер в tgu | Событие |
|---|---|---|
| `pcp.tgu.visibility-windows-changed.v1` | `VisibilityWindowsChangedConsumer` | изменение окон видимости |
| `pcp.tgu.satellite-plan-decision.v1` | `PlanDecisionConsumer` | решение по плану (принят/отклонён) |
| `pcp.tgu.layin-confirmed.v1` | `LayinConfirmedConsumer` | подтверждение закладки |
| `pcp.tgu.layin-failed.v1` | `LayinFailedConsumer` | ошибка закладки |
| `pcp.tgu.plan-not-accepted.v1` | `PlanNotAcceptedConsumer` | план не принят |
| `pcp.tgu.station-params-changed.v1` | `StationParamsChangedConsumer` | смена параметров станции |
---
## 3. HTTP/REST — карта вызовов между сервисами
Адреса берутся из `settings.*``pcp.services.*` (Spring Cloud Config). Клиенты — `WebClient`.
| Вызывающий сервис | Целевой сервис | Эндпоинты (примеры) | Назначение |
|---|---|---|---|
| `pcp-ui-service` (BFF) | `tle-monitoring` | `/v1/api/tle`, `/v1/api/tle/satellite/{id}` | TLE |
| | `pcp-satellite-catalog` | `/api/satellites`, `/api/satellites/{id}/observation-profile`, `/slot-profile`, `/api/satellite-groups` | каталог КА |
| | `pcp-complex-mission` | `/api/missions`, `/api/missions/{id}/drops/calculate`, `/api/com-plan/runs`, `/api/com-plan/process` | миссии и комплексные планы |
| | `pcp-dynamic-plan` | `/v1/main/calcPlan`, `/{runId}/result`, `/routes`, `/intervals` | динамические планы |
| | `pcp-request` (request / earth-grid) | `/v1/requests`, `/v1/requests/{id}/cells` | заявки и ячейки |
| | `pcp-stations` | `/api/stations`, `/api/stations/{id}` | станции |
| | `slots-service` | `/api/slots/...`, `/api/slots/booking[...]` | слоты и бронирования |
| | `pcp-ballistics` | `/api/satellites/{id}/asc-node`, `/flight-line`, `/orbit`, `/extract-time`, `/initial-conditions/current`, `/receive-rv`, `/api/tle/parse`, `/api/tle/point` | баллистика |
| | `pcp-coverage-scheme` | `/api/coverage-schemes/calculate` | схемы покрытия |
| | `pcp-tgu` | `/api/platforms`, `/api/plans[...]`, `/api/plans/{id}/dismiss`, `/restore`, `/test/tgu/plans/{id}/decision`, `/confirm-layin` | планы ТГУ |
| `pcp-tgu-service` | `pcp-mission-planing` (`mission-planing.base-url`) | `/api/missions/{id}/clone`, `/api/missions/blank`, `/api/missions/{id}` | управление миссиями плана |
| | `pcp-ballistics` (`ballistics.base-url`) | расчёт точек/баллистики (`ExternalPointsClient`) | внешние точки |
| | `ordinis.nstart.cloud` (внешний) | `/api/v1/spacecraft/records` (`platforms-url`) | классификатор платформ КА |
| `pcp-mission-planing` | `pcp-ballistics` | `/api/obj-view/mpl-square`, `/mpl-point`, `/cell-coverage/{cell}`, `/api/satellites/{id}/rva`, `/extract-time` | баллистика для планирования |
| | `pcp-complex-mission` | `/api/satellites/snapshots/{id}`, режимы КА | данные комплексной миссии |
| | `pcp-satellite-catalog` | `/api/satellites/{id}` | каталог КА |
| `pcp-complex-mission` | `pcp-ballistics` (`ic-service`) | расчёты НУ/баллистики | баллистика |
| | `pcp-satellite-catalog` | `/api/satellites`, `/api/satellites/batch` | каталог КА |
| | `slots-service` | покрытие/слоты (`CoverageBatchClient`, `SlotService`) | слоты |
| | `pcp-request` (`earth-grid`) | сетка Земли/ячейки (`EarthGridService`) | заявки/ячейки |
| | `pcp-coverage-scheme` | расчёт схемы покрытия | покрытие |
| `pcp-dynamic-plan` | `pcp-request` | `/v1/requests` (выборка заявок) | заявки |
| | `pcp-ballistics` | `/api/satellites/orbit/availability/{norad}`, `/extract-time`, `/api/obj-view/mpl-square` | баллистика |
| | `pcp-satellite-catalog` | `/api/satellites` | каталог КА |
| `pcp-coverage-scheme` | `pcp-ballistics` | `/api/obj-view/mpl-square`, `/mpl-point`, `/extract-time` | баллистика |
| | `pcp-complex-mission` | `/api/satellites/{id}` | данные КА/миссии |
| `pcp-ballistics` | `pcp-stations` | `/api/stations` | станции (для расчётов видимости) |
| `slots-service` | `pcp-satellite-catalog` | `/api/satellites`, `/batch`, `/slot-profile` | каталог КА |
| | `pcp-request` (`earth-grid`) | `/v1/requests`, `/cells` | заявки/ячейки |
| `tle-monitoring` | `pcp-satellite-catalog` | `/api/satellites` | каталог КА |
Все сервисы дополнительно ходят в `spring-cloud-config-server` (8888) за конфигом и регистрируются в `spring-boot-admin-server`.
### Граф зависимостей (кто кого зовёт по HTTP)
```
ui-service ──> почти все (BFF-агрегатор)
tgu ─────────> mission-planing, ballistics, (ordinis ext)
mission-planing ─> ballistics, complex-mission, satellite-catalog
complex-mission ─> ballistics, satellite-catalog, slots, request, coverage-scheme
dynamic-plan ───> request, ballistics, satellite-catalog
coverage-scheme ─> ballistics, complex-mission
ballistics ─────> stations
slots ──────────> satellite-catalog, request
tle-monitoring ─> satellite-catalog (+ CelesTrak внешний)
```
`pcp-ballistics` и `pcp-satellite-catalog` — наиболее востребованные «нижние» сервисы.
---
## 4. Camunda — процессы и воркеры
Используется **Camunda 8 (Zeebe)**, `io.camunda:camunda-spring-boot-4-starter:8.8.10`.
Брокер внешний: gRPC `camunda.k8s.265.nstart.cloud:30901` (dev) / `localhost:26500` (локально),
ключ `camunda.client.grpc-address`.
- **`pcp-tgu-service`** — *оркестратор*: содержит BPMN-определения, разворачивает их и запускает экземпляры процессов (`CamundaClient.newCreateInstanceCommand()`).
- **`pcp-mission-planing-service`** — *исполнитель*: реализует все job-воркеры (`@JobWorker` в `FlowService`).
### Процесс `createSatelliteMission`
BPMN: [createSatelliteMission.bpmn](../../services/pcp-tgu-service/src/main/resources/BPMN/createSatelliteMission.bpmn).
Запуск: `BpmnPlanIssueProcessStarter``IssueDuePlanWorker.issuePlanNow()``PlanController` `POST /api/plans/{planId}/issue`.
```
startSatelliteMission
→ [calculateSatelliteSurveyMissions] «Сформировать план съёмки»
→ [calculateSatelliteDropMissions] «Сформировать план сбросов»
→ [sendSatellitePlan] «Отправка плана в СПО УОГ»
→ endSatelliteMission
```
### Процесс `updateAcceptedPlanSlots`
BPMN: [updateAcceptedPlanSlots.bpmn](../../services/pcp-tgu-service/src/main/resources/BPMN/updateAcceptedPlanSlots.bpmn).
Запуск: `AcceptedPlanSlotsUpdateProcessStarter``AcceptedPlanSlotsUpdateWorker`.
```
start → [updateSlotsStatus] «Обновление статуса слотов» → end
```
### Соответствие job-type → воркер
Все воркеры — в `pcp-mission-planing-service`, [FlowService.kt](../../services/pcp-mission-planing-service/src/main/kotlin/space/nstart/pcp/pcp_mission_planing_service/service/FlowService.kt), `autoComplete = false` (ручной `newCompleteCommand`).
| Job type (BPMN) | Метод воркера | Процесс |
|---|---|---|
| `calculateSatelliteSurveyMissions` | `FlowService.surveyPlan` | createSatelliteMission |
| `calculateSatelliteDropMissions` | `FlowService.surveyDrop` | createSatelliteMission |
| `sendSatellitePlan` | `FlowService.sendPlan` | createSatelliteMission |
| `updateSlotsStatus` | `FlowService.confirmPlan` | updateAcceptedPlanSlots |
### Схема
```
pcp-tgu-service pcp-mission-planing-service
(оркестратор) (job-воркеры, FlowService)
PlanController POST /api/plans/{id}/issue
BpmnPlanIssueProcessStarter
│ newCreateInstanceCommand("createSatelliteMission")
┌─────────────── Zeebe / Camunda 8 broker (gRPC) ───────────────┐
│ calculateSatelliteSurveyMissions ─────────────────────────► surveyPlan
│ calculateSatelliteDropMissions ─────────────────────────► surveyDrop
│ sendSatellitePlan ─────────────────────────► sendPlan
└───────────────────────────────────────────────────────────────┘
AcceptedPlanSlotsUpdateProcessStarter
│ newCreateInstanceCommand("updateAcceptedPlanSlots")
┌─────────────── Zeebe broker ───────────────┐
│ updateSlotsStatus ───────────────────────► confirmPlan
└─────────────────────────────────────────────┘
```
> Связь между HTTP и Camunda: воркеры `pcp-mission-planing-service` в ходе выполнения задач
> сами ходят по HTTP в `pcp-ballistics`, `pcp-complex-mission`, `pcp-satellite-catalog`
> и публикуют Kafka-событие `pcp.slots.status.v1` (см. разделы 23).