[E10-3b] orchestrator: dynamic supergraph manager — recompose без рестарта #84

Closed
claude wants to merge 0 commits from feat/E10-3b-dynamic-supergraph into feat/E10-5-on-chain-watcher
Owner

Story 10.3b — Dynamic supergraph composition без рестарта gateway

Stacked: feat/E10-3b-dynamic-supergraph → feat/E10-5-on-chain-watcher → feat/E10-4-install-pipeline → apps-catalog (зонтик #64).

Проблема

Apollo Gateway по умолчанию получает СТАТИЧЕСКИЙ список subgraph'ов на bootstrap'е через IntrospectAndCompose. Polling-режим подхватывает изменения СХЕМЫ у уже известных subgraph'ов, но НЕ замечает появление НОВЫХ записей в registry. Story 10.4 install pipeline пишет в registry без рестарта — но gateway не видел эти записи до перезапуска контейнера.

Решение

Custom SupergraphManager (createDynamicSupergraphManager), который:

  1. На initialize: первый compose(registry.listForCompose()) → возвращает initialSdl.
  2. Запускает setInterval(pollIntervalMs) → читает registry → fingerprint = name:url sorted join.
  3. Если fingerprint не изменился → composer НЕ зовётся (CPU/сеть экономятся).
  4. Если изменился → recompose → update(newSdl) → gateway swap'ает supergraph in-memory.

Архитектура (паттерн портов как в #73, #74)

Manager изолирован двумя портами:

  • SupergraphComposerPort — собрать SDL из subgraph descriptors (реальный impl через @apollo/composition — follow-up);
  • SupergraphRegistryReader — узкий read-only view существующего SubgraphRegistryService.

Скрытая ловушка

Fingerprint обновляется ТОЛЬКО ПОСЛЕ успешного compose'а. Если поставить до — exception в composer'е навсегда залипает в устаревшем состоянии (следующий tick думает что состояние актуально, recompose не происходит). Покрыто continuity-тестом.

Тесты

7/7 green (jest fake timers):

  • initial compose: composer вызывается ровно один раз
  • tick без изменений → composer НЕ вызывается
  • tick с новой subgraph-записью → composer + update
  • tick с удалённой subgraph-записью → recompose
  • tick с изменённым URL → recompose
  • ошибка в composer'е НЕ ломает следующий tick (continuity)
  • cleanup() останавливает таймер

Что НЕ входит

  • Интеграция с Apollo Gateway (gateway.module.ts пока продолжает использовать IntrospectAndCompose напрямую) — отдельный PR feat/E10-3b-apollo-integration, требует @apollo/composition impl для SupergraphComposerPort.

Файлы

  • src/gateway/supergraph-manager.ts — менеджер + порты
  • src/gateway/supergraph-manager.spec.ts — юнит-тесты
## Story 10.3b — Dynamic supergraph composition без рестарта gateway Stacked: feat/E10-3b-dynamic-supergraph → feat/E10-5-on-chain-watcher → feat/E10-4-install-pipeline → apps-catalog (зонтик #64). ### Проблема Apollo Gateway по умолчанию получает СТАТИЧЕСКИЙ список subgraph'ов на bootstrap'е через `IntrospectAndCompose`. Polling-режим подхватывает изменения СХЕМЫ у уже известных subgraph'ов, но НЕ замечает появление НОВЫХ записей в registry. Story 10.4 install pipeline пишет в registry без рестарта — но gateway не видел эти записи до перезапуска контейнера. ### Решение Custom SupergraphManager (`createDynamicSupergraphManager`), который: 1. На initialize: первый `compose(registry.listForCompose())` → возвращает `initialSdl`. 2. Запускает `setInterval(pollIntervalMs)` → читает registry → fingerprint = `name:url` sorted join. 3. Если fingerprint не изменился → composer НЕ зовётся (CPU/сеть экономятся). 4. Если изменился → recompose → `update(newSdl)` → gateway swap'ает supergraph in-memory. ### Архитектура (паттерн портов как в #73, #74) Manager изолирован двумя портами: - `SupergraphComposerPort` — собрать SDL из subgraph descriptors (реальный impl через `@apollo/composition` — follow-up); - `SupergraphRegistryReader` — узкий read-only view существующего `SubgraphRegistryService`. ### Скрытая ловушка Fingerprint обновляется ТОЛЬКО ПОСЛЕ успешного compose'а. Если поставить до — exception в composer'е навсегда залипает в устаревшем состоянии (следующий tick думает что состояние актуально, recompose не происходит). Покрыто continuity-тестом. ### Тесты 7/7 green (jest fake timers): - initial compose: composer вызывается ровно один раз - tick без изменений → composer НЕ вызывается - tick с новой subgraph-записью → composer + update - tick с удалённой subgraph-записью → recompose - tick с изменённым URL → recompose - ошибка в composer'е НЕ ломает следующий tick (continuity) - cleanup() останавливает таймер ### Что НЕ входит - Интеграция с Apollo Gateway (`gateway.module.ts` пока продолжает использовать `IntrospectAndCompose` напрямую) — отдельный PR `feat/E10-3b-apollo-integration`, требует `@apollo/composition` impl для `SupergraphComposerPort`. ### Файлы - `src/gateway/supergraph-manager.ts` — менеджер + порты - `src/gateway/supergraph-manager.spec.ts` — юнит-тесты
ant added this to the AppsCatalog project 2026-06-05 07:51:12 +00:00
Author
Owner

Замещён консолидированным PR #117 (вся работа apps-catalog/Federation в одной ветке на dev). Закрываю как superseded.

Замещён консолидированным PR #117 (вся работа apps-catalog/Federation в одной ветке на dev). Закрываю как superseded.
claude closed this pull request 2026-06-09 12:01:44 +00:00

Pull request closed

Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: C9S/mono#84