Skip to content

feat(controlplane): add CreateFederatedSubgraphs batch rpc - #3152

Merged
thisisnithin merged 6 commits into
mainfrom
nithin/cosmo-393-batch-create-rpc
Aug 11, 2026
Merged

feat(controlplane): add CreateFederatedSubgraphs batch rpc#3152
thisisnithin merged 6 commits into
mainfrom
nithin/cosmo-393-batch-create-rpc

Conversation

@thisisnithin

@thisisnithin thisisnithin commented Aug 11, 2026

Copy link
Copy Markdown
Member

Summary by CodeRabbit

  • New Features

    • Added batch creation for multiple federated subgraphs in a single request.
    • Successful batch operations return the created subgraph names.
    • Added atomic processing to prevent partial creation when requests contain duplicates, invalid data, or inaccessible namespaces.
  • Bug Fixes

    • Standardized routing, subscription, protocol, and URL validation across subgraph creation, publishing, and updates.
    • Improved validation for event-driven, plugin, feature, and gRPC subgraphs.
    • Improved consistency when associating newly created subgraphs with federated graphs.

Adds CreateFederatedSubgraphs, which creates several subgraphs in a single request.

Every entry is validated before anything is written, and the writes share one transaction, so the request either creates all of the subgraphs or none of them. Duplicate names within the request, entries that already exist in the namespace, and invalid labels, names or routing URLs are all rejected up front, leaving nothing behind.

Creating a subgraph does not trigger a composition — a subgraph carries no schema until it is published — so this is purely a batched write. Schemas are published afterwards with PublishFederatedSubgraphs, which composes each affected graph once.

The routing and subscription validation that create, publish and update each carried their own near-identical copy of now lives in a single helper, parameterised by whether the routing URL is required (create, publish), optional (update) or absent (plugins). A few error messages are normalised as a result: Event-Driven Graphs becomes An Event-Driven Graph, some trailing periods are dropped, and publish's empty-routing-URL message now matches create's.

Reviewer notes

controlplane/test/subgraph/batch-create-subgraphs.test.ts covers the happy path, label matching (including unlabelled subgraphs against a graph with no label matchers), Event-Driven graphs, and each rejection case, asserting that a rejected batch creates nothing.

Checklist

Creates several subgraphs in a single request. Every entry is validated
before anything is written and the writes share one transaction, so the
request either creates all of the subgraphs or none of them. Creating a
subgraph triggers no composition, so this is purely a batched write;
schemas are published afterwards with PublishFederatedSubgraphs.

The routing and subscription validation that create, publish and update
each carried their own near-identical copy of now lives in a single
helper. The wording of a few error messages is normalised as a result.
@coderabbitai

coderabbitai Bot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 1cccaf0c-8696-4b7d-92eb-060c53e211d0

📥 Commits

Reviewing files that changed from the base of the PR and between b61dc0a and 670833f.

⛔ Files ignored due to path filters (2)
  • connect-go/gen/proto/wg/cosmo/platform/v1/platform.pb.go is excluded by !**/*.pb.go, !**/gen/**
  • connect-go/gen/proto/wg/cosmo/platform/v1/platformv1connect/platform.connect.go is excluded by !**/gen/**
📒 Files selected for processing (3)
  • controlplane/src/core/bufservices/subgraph/createFederatedSubgraphs.ts
  • controlplane/src/core/repositories/SubgraphRepository.ts
  • controlplane/src/core/services/ApolloMigrator.ts
🚧 Files skipped from review as they are similar to previous changes (3)
  • controlplane/src/core/services/ApolloMigrator.ts
  • controlplane/src/core/bufservices/subgraph/createFederatedSubgraphs.ts
  • controlplane/src/core/repositories/SubgraphRepository.ts

Walkthrough

The platform API now supports atomic creation of multiple federated subgraphs. The control plane adds authorization, validation, transaction handling, audit logging, and structured responses. Shared routing validation is used by create, publish, and update operations.

Changes

Batch federated subgraph creation

Layer / File(s) Summary
RPC contract and service wiring
proto/wg/cosmo/platform/v1/platform.proto, connect/src/wg/cosmo/platform/v1/platform-PlatformService_connectquery.ts, controlplane/src/core/bufservices/PlatformService.ts
The platform contract defines batch creation messages and the CreateFederatedSubgraphs RPC. Generated bindings and PlatformService expose the handler.
Shared routing validation
controlplane/src/core/util.ts, controlplane/src/core/bufservices/subgraph/*, controlplane/test/feature-subgraph/*, controlplane/test/subgraph/publish-subgraph.test.ts, controlplane/test/subgraph/update-subgraph.test.ts
validateSubgraphRouting centralizes routing, subscription, event-driven, plugin, feature-subgraph, and gRPC validation. Existing tests now expect standardized messages.
Batch repository persistence and call-site updates
controlplane/src/core/repositories/SubgraphRepository.ts, controlplane/src/core/bufservices/monograph/createMonograph.ts, controlplane/src/core/bufservices/plugin/validateAndFetchPluginData.ts, controlplane/src/core/services/ApolloMigrator.ts, controlplane/src/core/bufservices/subgraph/*
SubgraphRepository.create accepts arrays, performs batch persistence, and returns records in input order. Existing single-subgraph callers use the new array-based contract.
Batch handler and atomic persistence
controlplane/src/core/bufservices/subgraph/createFederatedSubgraphs.ts, controlplane/test/subgraph/batch-create-subgraphs.test.ts
The handler validates authorization, namespaces, names, labels, routing, and existing subgraphs. It creates entries in one transaction, records audit entries, and returns created names. Tests cover success, validation failures, duplicates, atomicity, and unknown namespaces.

Estimated code review effort: 4 (Complex) | ~60 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely identifies the main change: adding the CreateFederatedSubgraphs batch RPC to the control plane.
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.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (3)
controlplane/test/subgraph/batch-create-subgraphs.test.ts (2)

14-14: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Use camelCase for this variable.

Rename dbname to dbName and update its references. As per coding guidelines, **/*.{js,jsx,ts,tsx} requires camelCase for variable and function names.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@controlplane/test/subgraph/batch-create-subgraphs.test.ts` at line 14, Rename
the variable dbname to dbName in the batch-create-subgraphs test and update
every reference to use the camelCase name.

Source: Coding guidelines


16-17: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚖️ Poor tradeoff

Add explicit callback types.

Import type TestContext from vitest. Annotate each testContext parameter and add explicit return types to the describe, beforeAll, afterAll, and test callbacks.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@controlplane/test/subgraph/batch-create-subgraphs.test.ts` around lines 16 -
17, Add the Vitest type-only TestContext import, annotate every testContext
parameter with TestContext, and provide explicit return types for the describe,
beforeAll, afterAll, and test callbacks in the Batch create subgraphs tests
suite.

Source: Coding guidelines

controlplane/src/core/util.ts (1)

947-956: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consider extracting the input shape into an interface.

The coding guidelines prefer interfaces over type aliases for object shapes. The inline object literal for input is also reused conceptually by four call sites. An exported interface makes the contract easier to reference and document.

♻️ Proposed refactor
+export interface SubgraphRoutingValidationInput {
+  isEventDrivenGraph: boolean;
+  routingUrl?: string;
+  subscriptionUrl?: string;
+  subscriptionProtocol?: GraphQLSubscriptionProtocol;
+  websocketSubprotocol?: GraphQLWebsocketSubprotocol;
+  routingUrlRequirement: RoutingUrlRequirement;
+  isGrpcService?: boolean;
+  isFeatureSubgraph?: boolean;
+}
+
-export function validateSubgraphRouting(input: {
-  isEventDrivenGraph: boolean;
-  routingUrl?: string;
-  subscriptionUrl?: string;
-  subscriptionProtocol?: GraphQLSubscriptionProtocol;
-  websocketSubprotocol?: GraphQLWebsocketSubprotocol;
-  routingUrlRequirement: RoutingUrlRequirement;
-  isGrpcService?: boolean;
-  isFeatureSubgraph?: boolean;
-}): string | undefined {
+export function validateSubgraphRouting(input: SubgraphRoutingValidationInput): string | undefined {

As per coding guidelines: "Prefer interfaces over type aliases for object shapes in TypeScript".

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@controlplane/src/core/util.ts` around lines 947 - 956, Extract the inline
input object shape from validateSubgraphRouting into an exported interface, then
use that interface as the function’s input parameter type. Preserve all existing
properties, optionality, and types so the four call sites remain compatible.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@controlplane/src/core/bufservices/subgraph/createFederatedSubgraphs.ts`:
- Around line 194-224: In the request validation near the existing empty
`req.subgraphs` check, reject batches exceeding a fixed maximum before entering
the `opts.db.transaction` callback. Reuse an appropriate existing
validation/error pattern and ensure oversized requests never reach the
sequential creation loop.

---

Nitpick comments:
In `@controlplane/src/core/util.ts`:
- Around line 947-956: Extract the inline input object shape from
validateSubgraphRouting into an exported interface, then use that interface as
the function’s input parameter type. Preserve all existing properties,
optionality, and types so the four call sites remain compatible.

In `@controlplane/test/subgraph/batch-create-subgraphs.test.ts`:
- Line 14: Rename the variable dbname to dbName in the batch-create-subgraphs
test and update every reference to use the camelCase name.
- Around line 16-17: Add the Vitest type-only TestContext import, annotate every
testContext parameter with TestContext, and provide explicit return types for
the describe, beforeAll, afterAll, and test callbacks in the Batch create
subgraphs tests suite.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 2a5aec3d-632e-45bc-bb22-2c1a2c17ec03

📥 Commits

Reviewing files that changed from the base of the PR and between f8f0a76 and 2ebe73f.

📒 Files selected for processing (14)
  • connect/src/wg/cosmo/platform/v1/platform-PlatformService_connectquery.ts
  • connect/src/wg/cosmo/platform/v1/platform_pb.ts
  • controlplane/src/core/bufservices/PlatformService.ts
  • controlplane/src/core/bufservices/subgraph/createFederatedSubgraph.ts
  • controlplane/src/core/bufservices/subgraph/createFederatedSubgraphs.ts
  • controlplane/src/core/bufservices/subgraph/publishFederatedSubgraph.ts
  • controlplane/src/core/bufservices/subgraph/updateSubgraph.ts
  • controlplane/src/core/util.ts
  • controlplane/test/feature-subgraph/create-feature-subgraph.test.ts
  • controlplane/test/feature-subgraph/publish-feature-subgraph.test.ts
  • controlplane/test/subgraph/batch-create-subgraphs.test.ts
  • controlplane/test/subgraph/publish-subgraph.test.ts
  • controlplane/test/subgraph/update-subgraph.test.ts
  • proto/wg/cosmo/platform/v1/platform.proto

Subgraph creation takes an array and issues one statement per table
rather than one set per subgraph. Subgraphs sharing a label set within a
namespace resolve their federated graphs once, and the audit logs for a
batch are written in a single insert.

Inserted rows are paired with their input by name, so the result never
depends on the order postgres returns them in.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
controlplane/src/core/repositories/SubgraphRepository.ts (1)

205-229: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

Key the pairing map by namespace and name.

targetIdByName uses only entry.data.name as the key. Each entry carries its own namespaceId, and target names are unique per namespace, not per organization. If two entries share a name in different namespaces, the second entry overwrites the first. Both subgraph rows then receive the same targetId, and the returned DTOs are wrong for one entry.

All current callers pass a single namespace, so this is latent. A composite key removes the risk without changing behavior for single-namespace batches.

♻️ Proposed fix: composite pairing key
-      // Paired by name rather than by position, so the result never depends on
-      // the order postgres returns the inserted rows in.
-      const targetIdByName = new Map(insertedTargets.map((target) => [target.name, target.id]));
+      // Paired by (namespaceId, name) rather than by position, so the result never depends on
+      // the order postgres returns the inserted rows in, and names are unique per namespace.
+      const targetKeyOf = (namespaceId: string, name: string): string => `${namespaceId}:${name}`;
+      const targetIdByKey = new Map(
+        insertedTargets.map((target) => [targetKeyOf(target.namespaceId, target.name), target.id]),
+      );

Then replace every targetIdByName.get(entry.data.name)! with targetIdByKey.get(targetKeyOf(entry.data.namespaceId, entry.data.name))!.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@controlplane/src/core/repositories/SubgraphRepository.ts` around lines 205 -
229, Update the pairing logic around targetIdByName to use a composite key of
namespaceId and name, preventing entries with the same name in different
namespaces from overwriting one another. Introduce or reuse a consistent
targetKeyOf helper for both building the map from insertedTargets and looking up
each entry, replacing targetIdByName.get(entry.data.name) while preserving
single-namespace behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@controlplane/src/core/repositories/SubgraphRepository.ts`:
- Around line 205-229: Update the pairing logic around targetIdByName to use a
composite key of namespaceId and name, preventing entries with the same name in
different namespaces from overwriting one another. Introduce or reuse a
consistent targetKeyOf helper for both building the map from insertedTargets and
looking up each entry, replacing targetIdByName.get(entry.data.name) while
preserving single-namespace behavior.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 08105c87-29c8-4408-b8cd-6951e26e16d5

📥 Commits

Reviewing files that changed from the base of the PR and between 2ebe73f and fa1f377.

📒 Files selected for processing (7)
  • controlplane/src/core/bufservices/monograph/createMonograph.ts
  • controlplane/src/core/bufservices/plugin/validateAndFetchPluginData.ts
  • controlplane/src/core/bufservices/subgraph/createFederatedSubgraph.ts
  • controlplane/src/core/bufservices/subgraph/createFederatedSubgraphs.ts
  • controlplane/src/core/bufservices/subgraph/publishFederatedSubgraph.ts
  • controlplane/src/core/repositories/SubgraphRepository.ts
  • controlplane/src/core/services/ApolloMigrator.ts
🚧 Files skipped from review as they are similar to previous changes (3)
  • controlplane/src/core/bufservices/subgraph/publishFederatedSubgraph.ts
  • controlplane/src/core/bufservices/subgraph/createFederatedSubgraph.ts
  • controlplane/src/core/bufservices/subgraph/createFederatedSubgraphs.ts

# Conflicts:
#	connect/src/wg/cosmo/platform/v1/platform_pb.ts
@github-actions

github-actions Bot commented Aug 11, 2026

Copy link
Copy Markdown

Router image scan passed

✅ No security vulnerabilities found in image:

ghcr.io/wundergraph/cosmo/router:sha-e1f925636d06a3b31f3b445fcee98db0a26896ae

@codecov

codecov Bot commented Aug 11, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 91.86813% with 37 lines in your changes missing coverage. Please review.
✅ Project coverage is 43.96%. Comparing base (6b57d4c) to head (2406dca).
⚠️ Report is 2 commits behind head on main.

Files with missing lines Patch % Lines
...e/bufservices/subgraph/createFederatedSubgraphs.ts 85.87% 25 Missing ⚠️
controlplane/src/core/services/ApolloMigrator.ts 0.00% 11 Missing ⚠️
...lplane/src/core/repositories/SubgraphRepository.ts 98.86% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##            main    #3152       +/-   ##
==========================================
+ Coverage   1.87%   43.96%   +42.09%     
==========================================
  Files        330     1076      +746     
  Lines      46020   140553    +94533     
  Branches     522     7441     +6919     
==========================================
+ Hits         861    61792    +60931     
- Misses     44844    76910    +32066     
- Partials     315     1851     +1536     
Files with missing lines Coverage Δ
...ntrolplane/src/core/bufservices/PlatformService.ts 93.63% <100.00%> (ø)
.../src/core/bufservices/monograph/createMonograph.ts 57.05% <100.00%> (ø)
...e/bufservices/plugin/validateAndFetchPluginData.ts 92.90% <100.00%> (ø)
...re/bufservices/subgraph/createFederatedSubgraph.ts 87.50% <100.00%> (ø)
...e/bufservices/subgraph/publishFederatedSubgraph.ts 89.70% <100.00%> (ø)
...ne/src/core/bufservices/subgraph/updateSubgraph.ts 89.26% <100.00%> (ø)
controlplane/src/core/util.ts 81.75% <100.00%> (ø)
...lplane/src/core/repositories/SubgraphRepository.ts 91.75% <98.86%> (ø)
controlplane/src/core/services/ApolloMigrator.ts 1.35% <0.00%> (ø)
...e/bufservices/subgraph/createFederatedSubgraphs.ts 85.87% <85.87%> (ø)

... and 736 files with indirect coverage changes

🚀 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.

Comment thread controlplane/src/core/repositories/SubgraphRepository.ts Outdated
Comment thread controlplane/src/core/services/ApolloMigrator.ts Outdated
…ey hold

Drops the lookup maps in favour of pairing inserted rows with their input
by index, and migrates apollo graphs with a single create call rather
than one per subgraph.

The base subgraph mapping is now written only when a subgraph is
actually a feature subgraph, matching the sibling checks, rather than
whenever feature subgraph options are present.
@thisisnithin
thisisnithin enabled auto-merge (squash) August 11, 2026 13:35
@thisisnithin
thisisnithin merged commit 9543225 into main Aug 11, 2026
51 checks passed
@thisisnithin
thisisnithin deleted the nithin/cosmo-393-batch-create-rpc branch August 11, 2026 13:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants