Skip to content

feat(router): reuse unchanged feature flag muxes on graph server#2823

Open
dkorittki wants to merge 5 commits intofeat/split-configsfrom
dominik/eng-9495-router-optimize-graph-server-swap
Open

feat(router): reuse unchanged feature flag muxes on graph server#2823
dkorittki wants to merge 5 commits intofeat/split-configsfrom
dominik/eng-9495-router-optimize-graph-server-swap

Conversation

@dkorittki
Copy link
Copy Markdown
Contributor

@dkorittki dkorittki commented May 5, 2026

Makes use of the new split config poller, which has the ability to tell what feature flag configs have changed. We pass this information down to newGraphServer where we use it to reuse unchanged feature flag as well as base graph muxes. The change is backwards compatible: The old poller indicates it can' tell what changed and the callers then go the old path: rebuild everything.

Summary by CodeRabbit

  • New Features
    • Added support for split configuration loading based on feature flags, enabling routers to load configuration from multiple sources conditionally.
    • Enhanced JWT token payloads to include feature flag information for improved router-level feature detection and configuration selection.

Checklist

  • I have discussed my proposed changes in an issue and have received approval to proceed.
  • I have followed the coding standards of the project.
  • Tests or benchmarks have been added or updated.
  • Documentation has been updated on https://github.com/wundergraph/docs-website.
  • I have read the Contributors Guide.

Open Source AI Manifesto

This project follows the principles of the Open Source AI Manifesto. Please ensure your contribution aligns with its principles.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 5, 2026

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: cc969b43-6dc1-493c-8c86-281e43b4292b

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Walkthrough

This PR implements a feature-flag-based split-configuration loading mechanism for the router. It adds a new ActiveGraphs protobuf message, introduces a split-config-loading feature flag, enables JWT claims to carry feature information, and builds a polling system that assembles router configs from a base graph plus per-feature configuration files fetched via CDN.

Changes

Split-Config Loading Feature

Layer / File(s) Summary
Proto & Type Definitions
proto/wg/cosmo/node/v1/node.proto, connect/src/wg/cosmo/node/v1/node_pb.ts, controlplane/src/types/index.ts
ActiveGraphs message added (protobuf and TypeScript binding) with graphConfigs map field; FeatureIds extends to include 'split-config-loading'; GraphApiKeyJwtPayload adds optional features?: string[] claim.
Organization Feature Defaults
controlplane/src/core/repositories/OrganizationRepository.ts
getOrganizationFeatures initializes 'split-config-loading': false in the baseline feature map.
JWT Claim Generation
controlplane/src/core/bufservices/federated-graph/createFederatedGraphToken.ts
Token creation loads the split-config-loading feature flag and conditionally includes a features claim in the signed JWT when enabled.
JWT Claim Parsing
router/internal/jwt/claims.go
FederatedGraphTokenClaims gains a Features []string field with a HasFeature(feature string) bool helper; ExtractFederatedGraphTokenClaims validates and parses the features claim array.
Conditional Router Initialization
router/core/init_config_poller.go
InitializeConfigPoller detects the split-config-loading feature flag and returns a split-config poller immediately when enabled and no custom primary storage is configured; helper functions extract feature flags and construct the split poller.
Graph Mux Lifecycle & Reuse
router/core/graph_server.go, router/core/router.go
Feature-flag mux instances are tracked in activeFeatureFlagMuxes; muxes are reused across rebuilds when their engine config unchanged; mux contexts are scoped to graph-server lifetime and canceled during shutdown.
Split-Config HTTP Fetching
router/pkg/routerconfig/cdn/split_fetcher.go
SplitFetcher fetches mapper and per-feature configs from CDN via authenticated HTTP POST; supports gzip decompression, HMAC-SHA256 signature validation, and error code mapping.
Split-Config Polling & Assembly
router/pkg/controlplane/configpoller/split_config_poller.go
SplitConfigPoller polls the mapper at regular intervals, detects changes via composite-version hash, fetches only modified configs, assembles a full router config by merging base + per-feature entries, and invokes a handler with the patched config; internal state updates only after handler success.
Tests & Validation
router/pkg/controlplane/configpoller/split_config_poller_test.go, router/pkg/routerconfig/cdn/split_fetcher_test.go
Comprehensive unit tests for split-config poller (base-only, feature-flag addition/removal/change, error paths, state consistency) and fetcher (constructor validation, HTTP error mapping, request/response formatting, HMAC signature validation, proto-json parsing).

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes


Possibly related PRs

  • wundergraph/cosmo#2814: Introduces identical split-config loading architecture with ActiveGraphs protobuf, split-config-loading feature flag, JWT features claim support, and split-config poller/fetcher implementations.
🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 32.73% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The PR title 'feat(router) router optimize graph server swap' is vague and redundant, using the term 'router' twice without clearly communicating the main change about split-config loading, feature flags, or mux optimization. Consider a more descriptive title that clearly indicates the primary objective, such as 'feat(router): support split-config loading with feature flags and mux reuse' or 'feat: enable router split-config loading for feature-flag isolation'.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Comment @coderabbitai help to get the list of available commands and usage tips.

@dkorittki dkorittki changed the base branch from main to feat/split-configs May 5, 2026 12:43
@codecov
Copy link
Copy Markdown

codecov Bot commented May 5, 2026

Codecov Report

❌ Patch coverage is 61.05263% with 37 lines in your changes missing coverage. Please review.
⚠️ Please upload report for BASE (feat/split-configs@787d2d0). Learn more about missing BASE report.

Files with missing lines Patch % Lines
router/core/graph_server.go 54.54% 21 Missing and 4 partials ⚠️
router/core/router.go 63.63% 1 Missing and 3 partials ⚠️
...ter/pkg/controlplane/configpoller/config_poller.go 20.00% 4 Missing ⚠️
router/pkg/routerconfig/client.go 0.00% 3 Missing ⚠️
router/core/init_config_poller.go 0.00% 1 Missing ⚠️

❌ Your patch check has failed because the patch coverage (61.05%) is below the target coverage (90.00%). You can increase the patch coverage or adjust the target coverage.

Additional details and impacted files
@@                  Coverage Diff                  @@
##             feat/split-configs    #2823   +/-   ##
=====================================================
  Coverage                      ?   65.98%           
=====================================================
  Files                         ?      256           
  Lines                         ?    26845           
  Branches                      ?        0           
=====================================================
  Hits                          ?    17714           
  Misses                        ?     7728           
  Partials                      ?     1403           
Files with missing lines Coverage Δ
...g/controlplane/configpoller/split_config_poller.go 81.63% <100.00%> (ø)
router/core/init_config_poller.go 2.29% <0.00%> (ø)
router/pkg/routerconfig/client.go 0.00% <0.00%> (ø)
router/core/router.go 70.07% <63.63%> (ø)
...ter/pkg/controlplane/configpoller/config_poller.go 28.72% <20.00%> (ø)
router/core/graph_server.go 83.75% <54.54%> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 5, 2026

Router image scan passed

✅ No security vulnerabilities found in image:

ghcr.io/wundergraph/cosmo/router:sha-717ceb25160bdb9033e3d1f1a41764f26659f40d

dkorittki added 3 commits May 6, 2026 11:59
When a new graph server gets build it needs to know which muxes to replace
and which to keep. The split config poller can provide this information.
Since the config pollers are abstracted behind an interface I needed to extend
the interface. I did so by extending the routerconfig.Response type to include
a field which indicates what changed on the config. The old, default
config poller can't provide these information, so it returns nil.
nil indicates that no change information is provided. This must not be confused
with "no changes have happened" - two very different things.
It's expected that during graph server creation changes=nil is treated as
"rebuild everything".

This design ensures backwards compatibility:
router token has no split-config feature
=> use old config poller
=> provides changes=nil
=> graph server creation rebuilds everything.
@dkorittki dkorittki force-pushed the dominik/eng-9495-router-optimize-graph-server-swap branch from 86e7d25 to 454400e Compare May 6, 2026 15:23
@dkorittki dkorittki changed the title feat(router) router optimize graph server swap feat(router) reuse unchanged feature flag muxes on graph server May 6, 2026
@dkorittki dkorittki changed the title feat(router) reuse unchanged feature flag muxes on graph server feat(router): reuse unchanged feature flag muxes on graph server May 6, 2026
@dkorittki dkorittki marked this pull request as ready for review May 6, 2026 15:54
@dkorittki dkorittki removed the request for review from SkArchon May 6, 2026 16:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants