Files
dc-observatio/docs/architect/PCP_ARCHITECTURE.md
Дмитрий Соловьев 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

18 KiB
Raw Permalink Blame History

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.status.v1 (outbox → geoportal) 🟢 высокая
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 Отдельная SPA Mission Ops/TGU; карта возможностей и источников данных: PCP_TGU_OPS_UI_CAPABILITY_MAP.md
libs/pcp-types-lib Общие DTO и конверт KafkaMessage<T>, перечисление PcpKafkaEvent
libs/ballistics-lib Общие баллистические расчёты

2. Диаграммы взаимодействия

2.1. Синхронные зависимости (REST) — кто кого вызывает

Рёбра восстановлены из ключей *-service* base-url в config-repo и имён HTTP-клиентов в коде.

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) — потоки данных

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.status.v1 · COMPLETED/EXPIRED| GEO[geoportal · внешний]

    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 от заявки до выдачи задания на КА.

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.status.v1 request-service (outbox) geoportal (внешний) REQUEST_TERMINAL_STATUS (COMPLETED/EXPIRED) 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 — уточнено: потребитель терминальных статусов заявки = внешний geoportal, топик переименован в pcp.request.status.v1 (COMPLETED/EXPIRED, #35).
  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.