Skip to content

fix: ensure subgraph operation name is unique#2094

Merged
ysmolski merged 1 commit intomainfrom
yury/eng-7691-ensure-subgraph-operation-name-is-unique
Jul 31, 2025
Merged

fix: ensure subgraph operation name is unique#2094
ysmolski merged 1 commit intomainfrom
yury/eng-7691-ensure-subgraph-operation-name-is-unique

Conversation

@ysmolski
Copy link
Copy Markdown
Contributor

@ysmolski ysmolski commented Jul 30, 2025

Integration tests for the engine changes.
Tests that expect debug query plan were fixed to expect FetchID appended to the operation name.

Summary by CodeRabbit

  • New Features

    • Added integration tests to verify propagation of operation names to subgraph fetch requests when enabled in the engine configuration.
  • Bug Fixes

    • Updated operation name formats in query plan fixtures to include unique numeric suffixes for better traceability.
  • Documentation

    • Clarified the description of the operation name format in the configuration schema.
  • Chores

    • Upgraded a core dependency to a newer pre-release version.

Checklist

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jul 30, 2025

Walkthrough

This change updates the github.com/wundergraph/graphql-go-tools/v2 dependency to version v2.0.0-rc.215 in both router and router-tests. It adds a new integration test verifying operation name propagation to subgraph fetches. JSON fixtures are updated to reflect new operation name suffixes, and the configuration schema description is clarified regarding the operation name format.

Changes

Cohort / File(s) Change Summary
Dependency Update
router/go.mod, router-tests/go.mod
Updates the github.com/wundergraph/graphql-go-tools/v2 dependency from v2.0.0-rc.213 to v2.0.0-rc.215. No other dependency or module changes.
Integration Test Addition
router-tests/integration_test.go
Adds TestPropagateOperationName, a new integration test that verifies propagation of operation names to subgraph fetch requests when enabled. Includes subtests for simple and complex query scenarios, with middleware assertions and concurrency-safe tracking of expected operation names.
Query Plan Fixture Updates
router-tests/testdata/fixtures/query_plans/response_with_query_plan_operation_name.json, router-tests/testdata/fixtures/query_plans/response_with_query_plan_operation_name_sanitized_no_data.json
Updates operation names in GraphQL queries embedded in JSON fixtures by appending unique numeric suffixes (e.g., Requires__employees__0), consistent with the new operation naming pattern. No other structural or content changes.
Schema Description Update
router/pkg/config/config.schema.json
Revises the description of the enable_subgraph_fetch_operation_name configuration property to clarify the operation name format as $OperationName__$SubgraphName__$FetchID. No changes to schema structure or types.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~8 minutes

Possibly related PRs

  • fix: fix parent node jump lookup #2091: Updates the same github.com/wundergraph/graphql-go-tools/v2 dependency to a previous version (v2.0.0-rc.213), showing a direct connection in dependency management across related modules.

📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8eee9f8 and e3a9601.

⛔ Files ignored due to path filters (2)
  • router-tests/go.sum is excluded by !**/*.sum
  • router/go.sum is excluded by !**/*.sum
📒 Files selected for processing (6)
  • router-tests/go.mod (1 hunks)
  • router-tests/integration_test.go (2 hunks)
  • router-tests/testdata/fixtures/query_plans/response_with_query_plan_operation_name.json (5 hunks)
  • router-tests/testdata/fixtures/query_plans/response_with_query_plan_operation_name_sanitized_no_data.json (5 hunks)
  • router/go.mod (1 hunks)
  • router/pkg/config/config.schema.json (1 hunks)
✅ Files skipped from review due to trivial changes (3)
  • router/go.mod
  • router-tests/go.mod
  • router-tests/testdata/fixtures/query_plans/response_with_query_plan_operation_name.json
🚧 Files skipped from review as they are similar to previous changes (3)
  • router-tests/testdata/fixtures/query_plans/response_with_query_plan_operation_name_sanitized_no_data.json
  • router/pkg/config/config.schema.json
  • router-tests/integration_test.go
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (11)
  • GitHub Check: build-router
  • GitHub Check: image_scan
  • GitHub Check: image_scan (nonroot)
  • GitHub Check: integration_test (./. ./fuzzquery ./lifecycle ./modules)
  • GitHub Check: build_test
  • GitHub Check: integration_test (./telemetry)
  • GitHub Check: integration_test (./events)
  • GitHub Check: build_push_image
  • GitHub Check: build_push_image (nonroot)
  • GitHub Check: Analyze (go)
  • GitHub Check: Analyze (javascript-typescript)
✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch yury/eng-7691-ensure-subgraph-operation-name-is-unique

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jul 30, 2025

Router-nonroot image scan passed

✅ No security vulnerabilities found in image:

ghcr.io/wundergraph/cosmo/router:sha-437d53f20f22fa599beab295445c4f0d30abb4bc-nonroot

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (3)
router-tests/go.mod (1)

178-179: Delete the stale commented replace directive

The commented path override for graphql-go-tools/v2 is obsolete and may confuse future readers. Safely remove it:

-// github.com/wundergraph/graphql-go-tools/v2 => ../../graphql-go-tools/v2
router/pkg/config/config.schema.json (1)

2717-2721: Add an explicit example value and escape placeholders for better readability

The new description is clear, but adding an explicit example (using JSON-pointer style) makes it much easier for end-users and tooling to understand the resulting wire format, and wrapping the placeholders in back-ticks avoids accidental $ substitutions in some editors.

- "description": "Enable appending the operation name to subgraph fetches. This will ensure that the operation name will be included in the corresponding subgraph requests using the following format: $OperationName__$SubgraphName__$FetchID."
+ "description": "Enable appending the operation name to subgraph fetches. When enabled the router rewrites sub-requests so the operation name follows the format:\n\n  `\$OperationName__\$SubgraphName__\$FetchID`\n\nExample produced subgraph request name:\n\n```json\n{\n  \"operationName\": \"GetProducts__products__1\"\n}\n```"
router-tests/testdata/fixtures/query_plans/response_with_query_plan_operation_name_sanitized_no_data.json (1)

26-29: Confirm sanitisation of exotic sub-graph identifiers

The sanitised segments (mo_o_d, av_ai_la_bi_lit_y) strip unsafe characters, but the raw subgraphName fields still contain symbols like $, %, & that are illegal in GraphQL names.
Please double-check that only the sanitised value is ever used as an operation name, and consider asserting this invariant in unit tests to guard against future regressions.

Also applies to: 68-71

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 618d62b and 494266b.

⛔ Files ignored due to path filters (2)
  • router-tests/go.sum is excluded by !**/*.sum
  • router/go.sum is excluded by !**/*.sum
📒 Files selected for processing (6)
  • router-tests/go.mod (1 hunks)
  • router-tests/integration_test.go (2 hunks)
  • router-tests/testdata/fixtures/query_plans/response_with_query_plan_operation_name.json (5 hunks)
  • router-tests/testdata/fixtures/query_plans/response_with_query_plan_operation_name_sanitized_no_data.json (5 hunks)
  • router/go.mod (1 hunks)
  • router/pkg/config/config.schema.json (1 hunks)
🧰 Additional context used
🧠 Learnings (5)
📓 Common learnings
Learnt from: SkArchon
PR: wundergraph/cosmo#2090
File: router/pkg/config/config.schema.json:0-0
Timestamp: 2025-07-30T09:29:46.660Z
Learning: The "operation_name_trim_limit" configuration property in router/pkg/config/config.schema.json should be placed at the security level as a sibling to complexity_limits, not inside the complexity_limits object.
router-tests/testdata/fixtures/query_plans/response_with_query_plan_operation_name.json (1)

Learnt from: SkArchon
PR: #2090
File: router/core/operation_processor.go:0-0
Timestamp: 2025-07-30T09:29:04.257Z
Learning: GraphQL operation names don't allow characters with more than 1 code point, so string length operations and slicing work correctly for both byte and character counting in GraphQL operation name processing.

router/pkg/config/config.schema.json (1)

Learnt from: SkArchon
PR: #2090
File: router/pkg/config/config.schema.json:0-0
Timestamp: 2025-07-30T09:29:46.660Z
Learning: The "operation_name_trim_limit" configuration property in router/pkg/config/config.schema.json should be placed at the security level as a sibling to complexity_limits, not inside the complexity_limits object.

router-tests/testdata/fixtures/query_plans/response_with_query_plan_operation_name_sanitized_no_data.json (1)

Learnt from: SkArchon
PR: #2090
File: router/core/operation_processor.go:0-0
Timestamp: 2025-07-30T09:29:04.257Z
Learning: GraphQL operation names don't allow characters with more than 1 code point, so string length operations and slicing work correctly for both byte and character counting in GraphQL operation name processing.

router-tests/integration_test.go (1)

Learnt from: Noroth
PR: #2088
File: demo/pkg/subgraphs/projects/src/main_test.go:0-0
Timestamp: 2025-07-29T08:19:55.720Z
Learning: In Go testing, t.Fatal, t.FailNow, t.Skip* and similar methods cannot be called from goroutines other than the main test goroutine, as they will cause a runtime panic. Use channels, t.Error*, or other synchronization mechanisms to communicate errors from goroutines back to the main test thread.

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (12)
  • GitHub Check: build-router
  • GitHub Check: build_test
  • GitHub Check: build_push_image
  • GitHub Check: integration_test (./telemetry)
  • GitHub Check: image_scan
  • GitHub Check: build_push_image (nonroot)
  • GitHub Check: image_scan (nonroot)
  • GitHub Check: integration_test (./. ./fuzzquery ./lifecycle ./modules)
  • GitHub Check: integration_test (./events)
  • GitHub Check: build_test
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: Analyze (go)
🔇 Additional comments (7)
router-tests/go.mod (1)

29-29: Dependency bump approved – manual verification required

github.com/wundergraph/graphql-go-tools/v2 is now pinned to v2.0.0-rc.214-6af5027c19d2. No go.work file was detected, so please manually confirm that every module in the repo uses the identical commit:

  • List all version pins:
    grep -R 'github.com/wundergraph/graphql-go-tools/v2' -n .
  • For each module directory (e.g., router-tests/, router/, etc.):
    cd <module_dir>
    go mod tidy
    and ensure no mismatched versions appear.
router-tests/testdata/fixtures/query_plans/response_with_query_plan_operation_name_sanitized_no_data.json (1)

15-16: Operation-name uniqueness suffix looks correct – no further action required

All updated query strings now append __<fetchId> to the operation name, guaranteeing uniqueness across subgraph fetches while still starting with a non-reserved character. This satisfies the new router requirement and remains GraphQL-spec compliant.

Also applies to: 39-40, 81-82, 135-136, 194-195

router/go.mod (1)

34-36: Version bump is shadowed by the local replace – verify intent

require github.com/wundergraph/graphql-go-tools/v2 v2.0.0-rc.214… was updated, but the replace directive at Line 165 still points to a local checkout (../../graphql-go-tools/v2).
In Go modules the replace wins, so the build will ignore this new pseudo-version. If the intent is to test the upstream change, drop the replace or update the local checkout accordingly; otherwise the version bump is dead code.

router-tests/testdata/fixtures/query_plans/response_with_query_plan_operation_name.json (1)

33-34: Unique-suffixed operation names in fixture are consistent – looks good

The fixture now mirrors the router’s $OperationName__$Subgraph__$FetchID format across all fetch nodes. Alignment with the sanitised fixture and the new integration test is correct.

Also applies to: 57-58, 99-100, 153-154, 212-213

router-tests/integration_test.go (3)

17-17: LGTM! Clean import addition.

The slices package import is correctly added and will be used for slice operations in the new test function.


591-625: LGTM! Well-structured simple test case.

The test correctly:

  • Enables the operation name propagation feature via EnableSubgraphFetchOperationName
  • Validates the expected operation name format OperationName__SubgraphName__FetchID
  • Verifies variable remapping works as expected (counta)
  • Uses proper middleware interception to assert subgraph request content

The test implementation follows good practices and thoroughly validates the feature behavior.


627-711: LGTM! Comprehensive complex test case with proper concurrency handling.

The test excellently demonstrates:

  • Thread-safe tracking: Proper mutex usage around shared expectEmployeeOps slice operations
  • Multi-subgraph validation: Each subgraph middleware correctly validates expected operation names
  • Flexible assertions: Uses require.Contains for Mood/Availability subgraphs, allowing for implementation flexibility
  • Complete verification: Ensures all expected operations are encountered via require.Empty(t, expectEmployeeOps)
  • Proper request restoration: All middleware correctly restores request bodies with io.NopCloser

The synchronization logic using slices.Index and slices.Delete within mutex protection is correctly implemented and thread-safe.

Comment thread router-tests/integration_test.go
Copy link
Copy Markdown
Member

@jensneuse jensneuse left a comment

Choose a reason for hiding this comment

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

One minor comment

@ysmolski ysmolski force-pushed the yury/eng-7691-ensure-subgraph-operation-name-is-unique branch 3 times, most recently from 955c846 to 8eee9f8 Compare July 31, 2025 10:31
Copy link
Copy Markdown
Contributor

@StarpTech StarpTech left a comment

Choose a reason for hiding this comment

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

LGTM

Integration tests for the engine changes.
Tests that expect debug query plan were fixed to expect
FetchID appended to the operation name.
@ysmolski ysmolski force-pushed the yury/eng-7691-ensure-subgraph-operation-name-is-unique branch from 8eee9f8 to e3a9601 Compare July 31, 2025 11:42
@ysmolski ysmolski merged commit 0f47c69 into main Jul 31, 2025
28 checks passed
@ysmolski ysmolski deleted the yury/eng-7691-ensure-subgraph-operation-name-is-unique branch July 31, 2025 12:47
@Noroth Noroth mentioned this pull request Sep 30, 2025
5 tasks
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.

3 participants