Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

enhance: retry the request if the schema is reloaded during the request #818

Merged
merged 21 commits into from
Mar 14, 2025

Conversation

ardatan
Copy link
Member

@ardatan ardatan commented Mar 12, 2025

When the schema is reloaded during a query execution, retry the request instead of throwing a reload event error

Previously, it was throwing an error SCHEMA_RELOAD when the schema is changed during the request.

Waiting for user's confirmation to merge!

@theguild-bot
Copy link
Collaborator

theguild-bot commented Mar 12, 2025

🚀 Snapshot Release (alpha)

The latest changes of this PR are available as alpha on npm (based on the declared changesets):

Package Version Info
@graphql-mesh/fusion-runtime 0.11.4-alpha-7db7e2ccc8b399acae16e9269769a3b328e4827f npm ↗︎ unpkg ↗︎
@graphql-hive/gateway 1.12.1-alpha-7db7e2ccc8b399acae16e9269769a3b328e4827f npm ↗︎ unpkg ↗︎
@graphql-hive/nestjs 1.0.2-alpha-7db7e2ccc8b399acae16e9269769a3b328e4827f npm ↗︎ unpkg ↗︎
@graphql-hive/plugin-aws-sigv4 1.0.1-alpha-7db7e2ccc8b399acae16e9269769a3b328e4827f npm ↗︎ unpkg ↗︎
@graphql-mesh/plugin-opentelemetry 1.3.47-alpha-7db7e2ccc8b399acae16e9269769a3b328e4827f npm ↗︎ unpkg ↗︎
@graphql-mesh/plugin-prometheus 1.3.35-alpha-7db7e2ccc8b399acae16e9269769a3b328e4827f npm ↗︎ unpkg ↗︎
@graphql-hive/gateway-runtime 1.6.1-alpha-7db7e2ccc8b399acae16e9269769a3b328e4827f npm ↗︎ unpkg ↗︎

Copy link
Contributor

coderabbitai bot commented Mar 12, 2025

📝 Walkthrough

Summary by CodeRabbit

  • New Features

    • Introduced an automatic retry mechanism for queries when the schema reloads, ensuring smoother and more resilient operations.
    • Added support for dynamic schema updates through callback integration.
    • Enhanced GraphQL gateway configuration options for a more intuitive setup process.
  • Improvements

    • Refined error messages for configuration and subscription-related issues, providing clearer feedback during invalid inputs and schema reload events.

Walkthrough

This pull request implements several changes across the codebase. It introduces a new retry mechanism for schema reloads during query execution and refactors the unified graph management by adding an optional callback and consolidating cleanup methods. Test files have been updated to streamline asynchronous handling and to validate schema reload and subscription scenarios. Additionally, new files are added for gateway configuration, end-to-end tests, and for simulating upstream service behaviors. Minor modifications to error messaging and GitHub Actions workflows are also included.

Changes

File(s) Change Summary
.changeset/many-numbers-sell.md Introduced new retry behavior for handling schema reloads during query execution (schema is retried instead of erroring).
packages/fusion-runtime/src/unifiedGraphManager.ts, packages/runtime/src/createGatewayRuntime.ts, packages/runtime/src/plugins/useRetryOnSchemaReload.ts Added onUnifiedGraphChange callback; removed cleanup in favor of asyncDispose; integrated schema update logic via a new retry plugin; updated logging and error handling.
packages/fusion-runtime/tests/polling.test.ts, packages/runtime/tests/schema-reload.test.ts, packages/runtime/tests/subscriptions.test.ts Refactored test functions to use synchronous wrappers via handleMaybePromise; added tests for schema reload behavior and updated error codes/messages for subscriptions.
internal/e2e/src/example-setup.ts, internal/e2e/src/tenv.ts Modified the composeWithApollo call and signature to accept a structured options object and return a composed output object instead of a raw string.
packages/gateway/src/commands/supergraph.ts, packages/runtime/src/getReportingPlugin.ts Updated error messages to include specific invalid input details in the supergraph command; removed an unnecessary blank line in the reporting plugin.
.github/workflows/test.yml Set fail-fast: false for the e2e job, ensuring all matrix builds run even if some jobs fail.
e2e/graphos-polling/package.json, e2e/graphos-polling/gateway.config.ts Added a new package configuration for @e2e/graphos-polling and introduced a gateway configuration file for setting up GraphQL service parameters.
e2e/graphos-polling/graphos-polling.e2e.ts, e2e/graphos-polling/services/graphos.ts, e2e/graphos-polling/services/upstream_good.ts, e2e/graphos-polling/services/upstream_stuck.ts Added new end-to-end test files and service setup files that simulate GraphQL server behavior, including schema updates, a healthy upstream service, and a stalled upstream service to test retry logic.

📜 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 3b6d5ed and 8d1bdbf.

📒 Files selected for processing (2)
  • internal/e2e/src/tenv.ts (5 hunks)
  • internal/testing/src/getLocalhost.ts (2 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
`**`: For all PRs, we would like to verify that a Linear iss...

**: For all PRs, we would like to verify that a Linear issue is linked. Check if there's a mention for "GW-*" in the PR description, and the us know when it's missing.

In most cases, when a PR adds a new functionality, we would like to make sure it has documentation in the corresponding console project.
Use the global knowledge feature to search for PRs in graphql-hive/console repository that adds documentation. Suggest to create a follow up issue to add the missing documentation.

  • internal/testing/src/getLocalhost.ts
  • internal/e2e/src/tenv.ts
⏰ Context from checks skipped due to timeout of 90000ms (43)
  • GitHub Check: Examples / Convert operation-field-permissions
  • GitHub Check: Examples / Convert type-merging-batching
  • GitHub Check: Examples / Convert subscriptions-with-transforms
  • GitHub Check: Examples / Convert programmatic-batching
  • GitHub Check: Examples / Convert openapi-subscriptions
  • GitHub Check: Examples / Convert openapi-javascript-wiki
  • GitHub Check: Examples / Convert openapi-arg-rename
  • GitHub Check: Examples / Convert openapi-additional-resolvers
  • GitHub Check: Examples / Convert json-schema-subscriptions
  • GitHub Check: Examples / Convert interface-additional-resolvers
  • GitHub Check: Examples / Convert hmac-auth-https
  • GitHub Check: Examples / Convert federation-subscriptions-passthrough
  • GitHub Check: Examples / Convert apq-subgraphs
  • GitHub Check: Examples / Convert file-upload
  • GitHub Check: Examples / Convert federation-mixed
  • GitHub Check: Examples / Convert federation-example
  • GitHub Check: Examples / Convert extra-fields
  • GitHub Check: Binary built on ubuntu-24.04-arm
  • GitHub Check: Binary built on windows-latest
  • GitHub Check: Binary built on macos-14
  • GitHub Check: Binary built on macos-13
  • GitHub Check: Bun Docker image
  • GitHub Check: Binary built on ubuntu-latest
  • GitHub Check: Node Docker image
  • GitHub Check: E2E / Bun Docker on Ubuntu
  • GitHub Check: E2E / Bun on Ubuntu
  • GitHub Check: E2E / Node Binary on Windows
  • GitHub Check: E2E / Node Binary on Ubuntu
  • GitHub Check: E2E / Node Docker on Ubuntu
  • GitHub Check: E2E / Node 23 on Ubuntu
  • GitHub Check: Leaks / Node v23
  • GitHub Check: E2E / Node 22 on Ubuntu
  • GitHub Check: Benchmark / bun / 1000 items
  • GitHub Check: Leaks / Node v22
  • GitHub Check: Benchmark / bun / 100 items
  • GitHub Check: Benchmark / bun / 10 items
  • GitHub Check: E2E / Node 20 on Ubuntu
  • GitHub Check: Leaks / Node v20
  • GitHub Check: Benchmark / node / 1000 items
  • GitHub Check: Benchmark / node / 100 items
  • GitHub Check: E2E / Node 18 on Ubuntu
  • GitHub Check: Benchmark / node / 10 items
  • GitHub Check: Leaks / Node v18
🔇 Additional comments (11)
internal/testing/src/getLocalhost.ts (1)

6-9:

❓ Verification inconclusive

Improved flexibility by adding protocol parameter.

The addition of the optional protocol parameter enhances the function's flexibility while maintaining backward compatibility. The implementation consistently uses this parameter throughout the function, both in URL construction and the return statement.

Also applies to: 13-13, 28-28


🏁 Script executed:

#!/bin/bash
# Checking if the updated getLocalhost function is used with different protocols elsewhere in the codebase
echo "Searching for getLocalhost usage with explicit protocol parameter..."
rg "getLocalhost\([^,)]+,\s*['\"]https['\"]" --type ts

Length of output: 207


Enhanced flexibility verified – manual verification needed for protocol usage

The update in internal/testing/src/getLocalhost.ts (lines 6–9, also affecting lines 13 and 28) correctly adds the optional protocol parameter. This change is implemented in the URL construction and return statement, ensuring backward compatibility.

A shell script was run to find calls to getLocalhost with an explicit non-default protocol (e.g., 'https'), but no instances were found. Please manually verify that, where necessary, function calls across the codebase use the new parameter correctly or intentionally rely on the default.

internal/e2e/src/tenv.ts (10)

7-7: Good addition of the inspect utility.

Adding the inspect utility from the Node.js standard library is appropriate for the enhanced logging functionality implemented in the composeWithApollo method.


24-24: Appropriate import of the getLocalhost function.

The getLocalhost function is now properly imported from the testing utilities, which helps determine the correct hostname based on the gateway runner environment.


272-272: Improved method signature for better parameter handling.

The signature of composeWithApollo has been updated from accepting an array of services to accepting a structured options object, which is more flexible and consistent with other methods in the file.


385-387: Updated method call matches the new signature.

The call to composeWithApollo has been properly updated to use the new signature, passing an object with the services property.


967-977: Well-structured subgraph configuration.

The subgraph configuration now correctly determines the appropriate hostname based on the gateway runner type (Docker or local) using the imported getLocalhost function, which improves compatibility across different environments.


979-983: Enhanced logging implementation.

The addition of separate stdout, stderr, and combined (stdboth) logging variables provides better control and visibility into the composition process, which will be helpful for troubleshooting schema reload issues.


984-1026: Robust IntrospectAndCompose configuration.

The IntrospectAndCompose instance is now configured with a comprehensive logger that handles different log levels (debug, error, info, warn) and appropriately routes messages to stdout or stderr. The implementation also properly manages the supergraph SDL file creation and updates.


1027-1039: Improved schema handling and persistence.

The implementation now properly stores the supergraph SDL and writes it to a temporary file, which enables access to the schema for retry operations when reloading occurs.


1040-1061: Comprehensive return object with proper cleanup.

The return object now provides access to the output file, result string, and methods for retrieving statistics and standard output/error messages. The implementation also correctly handles cleanup through the DisposableSymbols.asyncDispose method.


1-1124: Missing Linear issue reference in PR description.

I noticed that the PR description doesn't include a reference to a Linear issue (GW-*). According to the project's coding guidelines, all PRs should have a Linear issue linked.

Could you please verify if there is a corresponding Linear issue for this PR and update the PR description accordingly?

🧰 Tools
🪛 Biome (1.9.4)

[error] 830-830: Avoid the use of spread (...) syntax on accumulators.

Spread syntax should be avoided on accumulators (like those in .reduce) because it causes a time complexity of O(n^2).
Consider methods such as .splice or .push instead.

(lint/performance/noAccumulatingSpread)


[error] 843-843: Avoid the use of spread (...) syntax on accumulators.

Spread syntax should be avoided on accumulators (like those in .reduce) because it causes a time complexity of O(n^2).
Consider methods such as .splice or .push instead.

(lint/performance/noAccumulatingSpread)

✨ Finishing Touches
  • 📝 Generate Docstrings

🪧 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.
    • Generate unit testing code for this file.
    • 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 generate unit testing code for this file.
    • @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 generate unit testing code.
    • @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.

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

@theguild-bot
Copy link
Collaborator

theguild-bot commented Mar 12, 2025

🚀 Snapshot Release (Binary for macOS-ARM64)

The latest changes of this PR are available for download (based on the declared changesets).

Download

@theguild-bot
Copy link
Collaborator

theguild-bot commented Mar 12, 2025

🚀 Snapshot Release (Binary for Linux-X64)

The latest changes of this PR are available for download (based on the declared changesets).

Download

@theguild-bot
Copy link
Collaborator

theguild-bot commented Mar 12, 2025

🚀 Snapshot Release (Node Docker Image)

The latest changes of this PR are available as image on GitHub Container Registry (based on the declared changesets):

ghcr.io/graphql-hive/gateway:1.12.1-alpha-7db7e2ccc8b399acae16e9269769a3b328e4827f

@theguild-bot
Copy link
Collaborator

theguild-bot commented Mar 12, 2025

🚀 Snapshot Release (Binary for Linux-ARM64)

The latest changes of this PR are available for download (based on the declared changesets).

Download

@theguild-bot
Copy link
Collaborator

theguild-bot commented Mar 12, 2025

🚀 Snapshot Release (Bun Docker Image)

The latest changes of this PR are available as image on GitHub Container Registry (based on the declared changesets):

ghcr.io/graphql-hive/gateway:1.12.1-alpha-7db7e2ccc8b399acae16e9269769a3b328e4827f-bun

@theguild-bot
Copy link
Collaborator

theguild-bot commented Mar 12, 2025

🚀 Snapshot Release (Binary for macOS-X64)

The latest changes of this PR are available for download (based on the declared changesets).

Download

@theguild-bot
Copy link
Collaborator

theguild-bot commented Mar 12, 2025

🚀 Snapshot Release (Binary for Windows-X64)

The latest changes of this PR are available for download (based on the declared changesets).

Download

Copy link
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: 1

🧹 Nitpick comments (5)
packages/runtime/src/plugins/useRetryOnSchemaReload.ts (1)

7-14: Avoid using {} as a type.

The WeakMap uses {} as a key type, which is discouraged in TypeScript. Empty object types don't provide type safety and can lead to unexpected behavior.

Consider using a more specific type or the object type instead:

- const execHandlerByContext = new WeakMap<
-   {},
-   () => MaybePromise<MaybeAsyncIterable<ExecutionResult>>
- >();
+ const execHandlerByContext = new WeakMap<
+   object,
+   () => MaybePromise<MaybeAsyncIterable<ExecutionResult>>
+ >();
🧰 Tools
🪛 Biome (1.9.4)

[error] 11-11: Don't use '{}' as a type.

Prefer explicitly define the object shape. '{}' means "any non-nullable value".

(lint/complexity/noBannedTypes)

packages/runtime/tests/schema-reload.test.ts (2)

52-75: Consider adding more test cases for error scenarios.

The current test only covers the happy path where the schema reload and retry succeed. Consider adding test cases for situations where retries fail or where multiple reloads occur.

// You could add an additional test case like:
+ it('handles multiple schema reloads correctly', async () => {
+   // Similar setup but with three schema versions and multiple reloads
+ });
+ 
+ it('handles retry failures appropriately', async () => {
+   // Setup where the second schema also has issues
+ });

76-110: Consider asserting the number of fetch attempts.

The test ensures the final result is correct, but it would be beneficial to verify that the retry mechanism worked as expected by checking that fetchCount equals 2 by the end of the test.

+ expect(fetchCount).toBe(2);
  expect(result).toMatchObject({
    data: {
      foo: 'barFromSecond',
    },
  });
packages/fusion-runtime/src/unifiedGraphManager.ts (2)

107-108: Consider adding documentation for onUnifiedGraphChange.

Introducing onUnifiedGraphChange is a great enhancement. Documenting its usage and any potential side effects in the JSDoc or the related README would help clarify its expected behavior and integration points.


169-175: Consider adding a retry or fallback mechanism here.

While logging and clearing this.polling$ is helpful when polling fails, you might want to add some logic to retry or wait before polling again. Otherwise, errors like network hiccups could permanently halt polling if not handled upstream.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 50d81e0 and 286f29a.

📒 Files selected for processing (7)
  • .changeset/many-numbers-sell.md (1 hunks)
  • packages/fusion-runtime/src/unifiedGraphManager.ts (4 hunks)
  • packages/fusion-runtime/tests/polling.test.ts (3 hunks)
  • packages/runtime/src/createGatewayRuntime.ts (4 hunks)
  • packages/runtime/src/plugins/useRetryOnSchemaReload.ts (1 hunks)
  • packages/runtime/tests/schema-reload.test.ts (1 hunks)
  • packages/runtime/tests/subscriptions.test.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
`packages/**`: In this directory we keep all packages releva...

packages/**: In this directory we keep all packages relevant to the gateway.

In most cases, when changes are made to the source code / dependencies in these directories, we also require to have a corresponding changeset file, created using yarn changeset with a full description on the changes with an example.
Also, when new features are added the packages, the changeset file should mention minor semver change. When a bug is fixed, patch needs to be used. The major bump is used for a PR that has breaking changes.

  • packages/runtime/src/plugins/useRetryOnSchemaReload.ts
  • packages/runtime/tests/subscriptions.test.ts
  • packages/fusion-runtime/tests/polling.test.ts
  • packages/runtime/tests/schema-reload.test.ts
  • packages/fusion-runtime/src/unifiedGraphManager.ts
  • packages/runtime/src/createGatewayRuntime.ts
`**`: For all PRs, we would like to verify that a Linear iss...

**: For all PRs, we would like to verify that a Linear issue is linked. Check if there's a mention for "GW-*" in the PR description, and the us know when it's missing.

In most cases, when a PR adds a new functionality, we would like to make sure it has documentation in the corresponding console project.
Use the global knowledge feature to search for PRs in graphql-hive/console repository that adds documentation. Suggest to create a follow up issue to add the missing documentation.

  • packages/runtime/src/plugins/useRetryOnSchemaReload.ts
  • packages/runtime/tests/subscriptions.test.ts
  • packages/fusion-runtime/tests/polling.test.ts
  • packages/runtime/tests/schema-reload.test.ts
  • packages/fusion-runtime/src/unifiedGraphManager.ts
  • packages/runtime/src/createGatewayRuntime.ts
🪛 Biome (1.9.4)
packages/runtime/src/plugins/useRetryOnSchemaReload.ts

[error] 11-11: Don't use '{}' as a type.

Prefer explicitly define the object shape. '{}' means "any non-nullable value".

(lint/complexity/noBannedTypes)

⏰ Context from checks skipped due to timeout of 90000ms (21)
  • GitHub Check: Examples / Convert openapi-arg-rename
  • GitHub Check: Examples / Convert federation-subscriptions-passthrough
  • GitHub Check: Binary built on ubuntu-24.04-arm
  • GitHub Check: Binary built on windows-latest
  • GitHub Check: Bun Docker image
  • GitHub Check: Binary built on macos-14
  • GitHub Check: Node Docker image
  • GitHub Check: Binary built on macos-13
  • GitHub Check: Binary built on ubuntu-latest
  • GitHub Check: E2E / Bun Docker on Ubuntu
  • GitHub Check: E2E / Node Binary on Windows
  • GitHub Check: E2E / Node Binary on Ubuntu
  • GitHub Check: E2E / Node Docker on Ubuntu
  • GitHub Check: E2E / Node 23 on Ubuntu
  • GitHub Check: Leaks / Node v23
  • GitHub Check: E2E / Node 22 on Ubuntu
  • GitHub Check: Leaks / Node v22
  • GitHub Check: E2E / Node 20 on Ubuntu
  • GitHub Check: Leaks / Node v20
  • GitHub Check: Leaks / Node v18
  • GitHub Check: Benchmark / bun / 10 items
🔇 Additional comments (18)
.changeset/many-numbers-sell.md (1)

1-7: LGTM! Changeset accurately describes the PR's purpose.

The changeset correctly specifies patch version updates for both affected packages and provides a clear, concise description of the change: retrying requests instead of throwing errors when schema reloads occur during query execution.

packages/runtime/tests/subscriptions.test.ts (1)

170-174: Error code and message updates appropriately distinguish subscription-specific behavior.

The changes make the error handling more precise by using a subscription-specific error code and message, which aligns with the PR objective of improving schema reload handling.

packages/runtime/src/plugins/useRetryOnSchemaReload.ts (2)

1-6: LGTM! Imports are appropriate for the plugin's functionality.

The imports cover all necessary utilities for handling async operations, execution results, and integration with the gateway plugin system.


15-23: LGTM! Handler registration is appropriately implemented.

The onParams hook correctly stores the execution handler in the WeakMap for later retrieval, using the context as the key. This pattern enables the retry mechanism to access the original handler when needed.

packages/runtime/tests/schema-reload.test.ts (2)

11-17: LGTM! Proper test cleanup.

The test correctly sets up and cleans up the interval using the afterAll hook to prevent resource leaks.


18-51: Well-structured test setup for schema reload scenario.

The test effectively simulates a schema reload scenario by creating two different upstream schemas - one that never resolves (simulating a long-running operation) and another with an immediate response.

packages/fusion-runtime/src/unifiedGraphManager.ts (4)

289-324: Mechanics for updating the unified graph look solid.

This block properly ensures the schema, updates the transport entry map, and composes subgraph logic. The approach appears both clear and robust.


325-353: Validate the forced closure of old subscriptions.

Setting this.disposeReason to SUBSCRIPTION_SCHEMA_RELOAD forcibly closes existing subscriptions, which is appropriate for preventing stale data. However, confirm that downstream consumers can gracefully handle the 503 status code, if relevant.


434-458: Async disposal logic is well-structured.

Centralizing the disposal of transportExecutorStack and executor in [DisposableSymbols.asyncDispose] helps maintain clarity. The approach of setting them to undefined reduces potential memory leaks.


461-473: Helper function for parallel disposal is well-organized.

disposeAll nicely handles synchronous and async disposables, ensuring each disposal is initiated. This improves code reuse and clarity in the disposal phase.

packages/fusion-runtime/tests/polling.test.ts (4)

17-20: New imports align with the refactoring approach.

Bringing in DeferredPromise and handleMaybePromise is suitable for coordinating asynchronous logic in a more controlled fashion.


81-95: Method conversion to handleMaybePromise is consistent.

Refactoring getFetchedTimeOnComment() to use handleMaybePromise preserves asynchronous handling and keeps the test code succinct.


97-119: Synchronous form with handleMaybePromise adds clarity.

Switching from async functions to returning handleMaybePromise appears consistent with the new pattern. Just ensure the final result is properly awaited in all calling code.


121-133: Helper to compare times is well-structured.

compareTimes() now sequentially flows through handleMaybePromise, improving consistency across the test suite.

packages/runtime/src/createGatewayRuntime.ts (4)

101-101: Including useRetryOnSchemaReload improves reliability.

Importing and using the new plugin helps ensure requests are retried if the schema reloads mid-request. This aligns with the PR’s main objective.


195-197: Ensure concurrency-safety when replacing schemas.

replaceSchema(newSchema) sets the new schema immediately, which is typically fine. In high-traffic scenarios, consider confirming that multiple near-simultaneous reloads don’t cause race conditions or partial updates.


690-693: Callback approach for onUnifiedGraphChange is well integrated.

Invoking both unifiedGraph = newUnifiedGraph and replaceSchema(newUnifiedGraph) ensures consistent updates in the gateway runtime and external references.


973-973: Adding useRetryOnSchemaReload to the plugin chain.

This final integration fully activates the retry logic in the gateway. The placement in basePlugins seems appropriate for capturing schema reload events early.

Copy link
Member

@dotansimha dotansimha left a comment

Choose a reason for hiding this comment

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

just add e2e test and we are good to go 🚀

Copy link
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: 1

🔭 Outside diff range comments (2)
e2e/graphos-polling/services/graphos.ts (2)

1-79: 💡 Verification agent

🧩 Analysis chain

Linear issue reference missing in PR description

The PR appears to be missing a reference to a Linear issue (GW-*) in the description. This is required according to your coding guidelines.


🏁 Script executed:

#!/bin/bash
# Check for Linear issue reference in the PR description

# Get PR description
PR_DESC=$(gh pr view 818 --json body -q .body)

# Check if it contains GW-* pattern
if echo "$PR_DESC" | grep -q "GW-[0-9]\+"; then
  echo "✅ Linear issue reference found in PR description"
else
  echo "❌ Linear issue reference missing in PR description"
  echo "PR description should contain a reference to a Linear issue (GW-*)"
fi

Length of output: 768


Action Required: Add Linear Issue Reference in PR Description

It appears that the PR description is missing the required Linear issue reference (GW-*). Please update the PR description with a valid Linear issue identifier to comply with the coding guidelines.


1-79: 💡 Verification agent

🧩 Analysis chain

Documentation might be needed for this new functionality

This PR adds new functionality for retrying requests when schema is reloaded. According to the coding guidelines, new functionality should have corresponding documentation in the console project.


🌐 Web query:

Are there any pull requests in graphql-hive/console repository that add documentation for schema reload retry functionality?

💡 Result:

Based on the provided search results, there are no specific pull requests mentioned in the graphql-hive/console repository that document schema reload retry functionality. However, the documentation does cover related schema management features:

  1. Schema Reload Mechanics:
    The Hive CLI supports schema reloads through commands like hive dev --remote --watch, which automatically updates the supergraph when local schemas change[1][3]. This enables hot-reloading during local development without explicit retry logic.

  2. GitHub Integration:
    The CLI supports --github and --contextId flags to retain schema check approvals within PR/branch lifecycles[1][6]. Failed checks can be manually approved through the Hive interface[4], but automatic retry behavior isn't documented.

  3. Error Handling:
    While error codes 110-112 are documented for GitHub integration failures[1], and schema changes automatically close active subscriptions with an error message[14], there's no mention of built-in retry mechanisms for schema reloads in the provided documentation.

For detailed implementation history, you'd need to examine the repository's pull requests directly, as the search results don't include specific PR discussions about retry functionality.

Citations:


Action Required: Update Documentation for Retry Functionality

The implementation of retrying requests on schema reload looks correct, but our investigation confirms there is currently no explicit documentation in the console project covering this new retry mechanism. Since our coding guidelines require new functionality to be documented, please add or update the relevant documentation in the console project to detail:

  • How the retry behavior works during schema reloads.
  • Any new error codes, configurations, or CLI flags (if applicable) related to this functionality.
  • Guidelines on expected behavior and troubleshooting steps for end users.
🧹 Nitpick comments (1)
e2e/graphos-polling/services/upstreamStuck.ts (1)

19-24: The resolver intentionally never resolves which could lead to memory leaks in tests.

This Promise is created but never resolved or rejected, which could potentially lead to memory leaks in long-running test scenarios. While this is intentional for testing purposes, it would be good to add a comment explaining why this approach was chosen rather than using a very long timeout or other techniques.

 foo: () =>
   new Promise(() => {
     console.log('foo on upstreamStuck');
-    // never resolves
+    // Intentionally never resolves to simulate a stuck upstream service
+    // This is used to test the retry mechanism during schema reload
   }),
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 286f29a and 6f96142.

⛔ Files ignored due to path filters (1)
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (8)
  • e2e/graphos-polling/graphos-polling.e2e.ts (1 hunks)
  • e2e/graphos-polling/package.json (1 hunks)
  • e2e/graphos-polling/services/graphos.ts (1 hunks)
  • e2e/graphos-polling/services/upstreamGood.ts (1 hunks)
  • e2e/graphos-polling/services/upstreamStuck.ts (1 hunks)
  • internal/e2e/src/example-setup.ts (1 hunks)
  • internal/e2e/src/tenv.ts (4 hunks)
  • packages/gateway/src/commands/supergraph.ts (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • e2e/graphos-polling/package.json
🧰 Additional context used
📓 Path-based instructions (4)
`e2e/**`: This directory includes end-to-end tests for the g...

e2e/**: This directory includes end-to-end tests for the gateway.
The examples directory is generated based on the code in this directory.

  • e2e/graphos-polling/services/upstreamGood.ts
  • e2e/graphos-polling/services/upstreamStuck.ts
  • e2e/graphos-polling/graphos-polling.e2e.ts
  • e2e/graphos-polling/services/graphos.ts
`**`: For all PRs, we would like to verify that a Linear iss...

**: For all PRs, we would like to verify that a Linear issue is linked. Check if there's a mention for "GW-*" in the PR description, and the us know when it's missing.

In most cases, when a PR adds a new functionality, we would like to make sure it has documentation in the corresponding console project.
Use the global knowledge feature to search for PRs in graphql-hive/console repository that adds documentation. Suggest to create a follow up issue to add the missing documentation.

  • e2e/graphos-polling/services/upstreamGood.ts
  • e2e/graphos-polling/services/upstreamStuck.ts
  • internal/e2e/src/example-setup.ts
  • packages/gateway/src/commands/supergraph.ts
  • e2e/graphos-polling/graphos-polling.e2e.ts
  • e2e/graphos-polling/services/graphos.ts
  • internal/e2e/src/tenv.ts
`packages/**`: In this directory we keep all packages releva...

packages/**: In this directory we keep all packages relevant to the gateway.

In most cases, when changes are made to the source code / dependencies in these directories, we also require to have a corresponding changeset file, created using yarn changeset with a full description on the changes with an example.
Also, when new features are added the packages, the changeset file should mention minor semver change. When a bug is fixed, patch needs to be used. The major bump is used for a PR that has breaking changes.

  • packages/gateway/src/commands/supergraph.ts
`packages/gateway/**`: The main runtime for the Hive gateway...

packages/gateway/**: The main runtime for the Hive gateway.
This package is CLI that runs the gateway and configures the internals of the gateway function.

  • packages/gateway/src/commands/supergraph.ts
⏰ Context from checks skipped due to timeout of 90000ms (42)
  • GitHub Check: Examples / Convert operation-field-permissions
  • GitHub Check: Examples / Convert type-merging-batching
  • GitHub Check: Examples / Convert subscriptions-with-transforms
  • GitHub Check: Examples / Convert programmatic-batching
  • GitHub Check: Examples / Convert openapi-javascript-wiki
  • GitHub Check: Examples / Convert openapi-arg-rename
  • GitHub Check: Examples / Convert openapi-additional-resolvers
  • GitHub Check: Examples / Convert json-schema-subscriptions
  • GitHub Check: Examples / Convert interface-additional-resolvers
  • GitHub Check: Examples / Convert hmac-auth-https
  • GitHub Check: Examples / Convert federation-subscriptions-passthrough
  • GitHub Check: Examples / Convert apq-subgraphs
  • GitHub Check: Examples / Convert federation-mixed
  • GitHub Check: Examples / Convert federation-example
  • GitHub Check: Examples / Convert extra-fields
  • GitHub Check: Binary built on ubuntu-24.04-arm
  • GitHub Check: Binary built on windows-latest
  • GitHub Check: Binary built on macos-14
  • GitHub Check: Binary built on macos-13
  • GitHub Check: Bun Docker image
  • GitHub Check: Binary built on ubuntu-latest
  • GitHub Check: Node Docker image
  • GitHub Check: E2E / Bun Docker on Ubuntu
  • GitHub Check: E2E / Bun on Ubuntu
  • GitHub Check: E2E / Node Binary on Windows
  • GitHub Check: E2E / Node Binary on Ubuntu
  • GitHub Check: E2E / Node Docker on Ubuntu
  • GitHub Check: E2E / Node 23 on Ubuntu
  • GitHub Check: E2E / Node 22 on Ubuntu
  • GitHub Check: Unit / Node v18
  • GitHub Check: Leaks / Node v23
  • GitHub Check: E2E / Node 20 on Ubuntu
  • GitHub Check: Leaks / Node v22
  • GitHub Check: E2E / Node 18 on Ubuntu
  • GitHub Check: Leaks / Node v20
  • GitHub Check: Leaks / Node v18
  • GitHub Check: Benchmark / bun / 1000 items
  • GitHub Check: Benchmark / bun / 100 items
  • GitHub Check: Benchmark / bun / 10 items
  • GitHub Check: Benchmark / node / 1000 items
  • GitHub Check: Benchmark / node / 100 items
  • GitHub Check: Benchmark / node / 10 items
🔇 Additional comments (13)
packages/gateway/src/commands/supergraph.ts (2)

32-267: Verify that a Linear issue is linked to this PR.

According to the coding guidelines, all PRs should reference a Linear issue with "GW-*" in the PR description. Please ensure this requirement is met.


1-406:

❓ Verification inconclusive

Ensure a changeset file was created for this change.

The PR implements a retry mechanism for schema reloads during query execution, which is a new feature. According to the coding guidelines, changes to packages under packages/gateway/** should be documented with a changeset file created using yarn changeset with a full description of the changes and an example. This would be a minor semver change since it's adding a new feature.


🏁 Script executed:

#!/bin/bash
# Check if a changeset file exists in the PR
git diff --name-only origin/main... | grep -E "\.changeset/.*\.md"

Length of output: 109


Action Required: Add a Changeset File Using yarn changeset
It appears that our automated check for changeset files encountered an error (no merge base found), so we couldn’t confirm whether a changeset file was added or not. Please manually verify that a changeset file exists in your PR (under the .changeset folder) to document the new retry mechanism for schema reloads. According to our guidelines, this new feature should be accompanied by a detailed changeset (a minor semver change).

🧰 Tools
🪛 Biome (1.9.4)

[error] 298-298: Avoid the delete operator which can impact performance.

Unsafe fix: Use an undefined assignment instead.

(lint/performance/noDelete)

e2e/graphos-polling/services/upstreamGood.ts (1)

1-31: LGTM! Good implementation of the test service.

The service is correctly implemented to complement the upstreamStuck service in the test scenario. It properly returns "bar" when the foo query is executed, enabling verification of the retry mechanism.

internal/e2e/src/example-setup.ts (1)

28-30: Updated to handle new composition result structure.

The code now correctly extracts the output property from the composition result, which indicates that composeWithApollo now returns a more complex object rather than just a string. This change properly aligns with modifications in the API structure.

e2e/graphos-polling/graphos-polling.e2e.ts (2)

6-12: Good cleanup practice for interval resources.

Properly cleaning up the interval in the afterAll hook ensures that resources are released after the test completes, preventing potential memory leaks.


14-73: Well-structured test for schema reload retry behavior.

This test effectively verifies the retry mechanism by:

  1. Setting up a service that never resolves (upstreamStuck)
  2. Executing a query against it
  3. Switching the schema to a service that does resolve (upstreamGood)
  4. Verifying that the original query completes successfully

The test demonstrates that the system now retries requests when schemas are reloaded during execution, which aligns with the PR objective.

Can you verify if a Linear issue for "GW-*" is mentioned in the PR description? According to the coding guidelines, all PRs should have a linked Linear issue.

internal/e2e/src/tenv.ts (4)

270-270: Updated function signature to return Compose object

The interface for composeWithApollo has been updated to return Promise<Compose> instead of a simple string. This change aligns with the implementation and provides a more structured return value with access to the output file path, result content, and cleanup methods.


383-384: Updated destructuring to match new return type

The code now correctly destructures the output property from the Compose object returned by composeWithApollo. This matches the updated function implementation.


972-982: Store IntrospectAndCompose instance for later cleanup

The implementation now stores the IntrospectAndCompose instance in a variable instead of directly accessing its supergraphSdl property. This allows for proper resource cleanup through the cleanup() method later.


983-994: Enhanced return object with proper cleanup support

The function now returns a comprehensive Compose object that includes the output file path, result content, placeholder methods for stats and logs, and most importantly, an asyncDispose method that properly cleans up resources by calling introspectAndCompose.cleanup().

This change supports the PR's objective of retrying requests during schema reloads by ensuring proper resource management.

e2e/graphos-polling/services/graphos.ts (3)

1-8: Good implementation of a mock GraphOS server

The import statements and setup are clean and well-organized. The server uses graphql-yoga for the GraphQL implementation and maintains state through the supergraphSDL variable, which is appropriate for this testing scenario.


9-68: Well-structured GraphQL schema for testing schema reloads

The schema definition is comprehensive and includes all necessary types for simulating GraphOS behavior:

  • RouterConfigResults union supports different response types
  • RouterConfigResult includes the supergraph SDL and other metadata
  • The mutation setSupergraphSDL allows for dynamic schema updates

This design properly supports the PR objective of testing retry behavior during schema reloads.


69-78: Simple and effective server setup

The server setup is minimal but sufficient for testing purposes. It creates a GraphQL server using Yoga and listens on the port provided by the testing options.

One small improvement could be to add error handling for the server startup, but this is acceptable for a test service.

@ardatan ardatan force-pushed the retry branch 2 times, most recently from 00900a0 to 3f027c2 Compare March 12, 2025 12:37
Copy link
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 (6)
e2e/graphos-polling/services/graphos.ts (5)

5-5: Add or confirm a reference to GW- (Linear) in the PR description.*

According to the coding guidelines, every PR should reference a Linear issue (e.g., "GW-*"). Please confirm whether this is tracked elsewhere or add the reference for proper traceability.


7-8: Consider concurrency or multi-threaded scenarios.

supergraphSDL is stored in a global variable, which might lead to data inconsistencies under high concurrency if multiple requests mutate it simultaneously.


53-59: Validate or utilize query parameters.

The routerConfig resolver ignores ref, apiKey, and ifAfterId. If these are intended for dynamic logic (e.g., conditional responses), consider implementing proper authorization, parameter validation, or usage in subsequent logic.


62-66: Validate SDL input before updating.

The mutation blindly updates supergraphSDL without checks. Consider validating or sanitizing the provided SDL for correctness or security concerns before storing it.


74-78: Handle server startup failures and document usage.

Currently, no error handling or logging is done if the server fails to start (port in use, etc.). Also, consider creating or referencing documentation in the console project for this new service to help developers understand configuration and usage.

packages/runtime/src/plugins/useRetryOnSchemaReload.ts (1)

11-11: Avoid using empty object type.

The WeakMap key is defined as an empty object type {}, which is generally discouraged.

-  const execHandlerByContext = new WeakMap<
-    {},
-    () => MaybePromise<MaybeAsyncIterable<ExecutionResult>>
-  >();
+  const execHandlerByContext = new WeakMap<
+    Record<string, unknown>,
+    () => MaybePromise<MaybeAsyncIterable<ExecutionResult>>
+  >();
🧰 Tools
🪛 Biome (1.9.4)

[error] 11-11: Don't use '{}' as a type.

Prefer explicitly define the object shape. '{}' means "any non-nullable value".

(lint/complexity/noBannedTypes)

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 6f96142 and d94dde6.

⛔ Files ignored due to path filters (18)
  • examples/apq-subgraphs/example.tar.gz is excluded by !**/*.gz
  • examples/extra-fields/example.tar.gz is excluded by !**/*.gz
  • examples/federation-example/example.tar.gz is excluded by !**/*.gz
  • examples/federation-mixed/example.tar.gz is excluded by !**/*.gz
  • examples/federation-subscriptions-passthrough/example.tar.gz is excluded by !**/*.gz
  • examples/file-upload/example.tar.gz is excluded by !**/*.gz
  • examples/hmac-auth-https/example.tar.gz is excluded by !**/*.gz
  • examples/interface-additional-resolvers/example.tar.gz is excluded by !**/*.gz
  • examples/json-schema-subscriptions/example.tar.gz is excluded by !**/*.gz
  • examples/openapi-additional-resolvers/example.tar.gz is excluded by !**/*.gz
  • examples/openapi-arg-rename/example.tar.gz is excluded by !**/*.gz
  • examples/openapi-javascript-wiki/example.tar.gz is excluded by !**/*.gz
  • examples/openapi-subscriptions/example.tar.gz is excluded by !**/*.gz
  • examples/operation-field-permissions/example.tar.gz is excluded by !**/*.gz
  • examples/programmatic-batching/example.tar.gz is excluded by !**/*.gz
  • examples/subscriptions-with-transforms/example.tar.gz is excluded by !**/*.gz
  • examples/type-merging-batching/example.tar.gz is excluded by !**/*.gz
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (15)
  • .changeset/many-numbers-sell.md (1 hunks)
  • e2e/graphos-polling/graphos-polling.e2e.ts (1 hunks)
  • e2e/graphos-polling/package.json (1 hunks)
  • e2e/graphos-polling/services/graphos.ts (1 hunks)
  • e2e/graphos-polling/services/upstreamGood.ts (1 hunks)
  • e2e/graphos-polling/services/upstreamStuck.ts (1 hunks)
  • internal/e2e/src/example-setup.ts (1 hunks)
  • internal/e2e/src/tenv.ts (4 hunks)
  • packages/fusion-runtime/src/unifiedGraphManager.ts (4 hunks)
  • packages/fusion-runtime/tests/polling.test.ts (3 hunks)
  • packages/gateway/src/commands/supergraph.ts (1 hunks)
  • packages/runtime/src/createGatewayRuntime.ts (4 hunks)
  • packages/runtime/src/plugins/useRetryOnSchemaReload.ts (1 hunks)
  • packages/runtime/tests/schema-reload.test.ts (1 hunks)
  • packages/runtime/tests/subscriptions.test.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (10)
  • e2e/graphos-polling/package.json
  • .changeset/many-numbers-sell.md
  • e2e/graphos-polling/services/upstreamStuck.ts
  • packages/runtime/tests/subscriptions.test.ts
  • internal/e2e/src/example-setup.ts
  • packages/gateway/src/commands/supergraph.ts
  • packages/runtime/tests/schema-reload.test.ts
  • internal/e2e/src/tenv.ts
  • e2e/graphos-polling/graphos-polling.e2e.ts
  • e2e/graphos-polling/services/upstreamGood.ts
🧰 Additional context used
📓 Path-based instructions (3)
`packages/**`: In this directory we keep all packages releva...

packages/**: In this directory we keep all packages relevant to the gateway.

In most cases, when changes are made to the source code / dependencies in these directories, we also require to have a corresponding changeset file, created using yarn changeset with a full description on the changes with an example.
Also, when new features are added the packages, the changeset file should mention minor semver change. When a bug is fixed, patch needs to be used. The major bump is used for a PR that has breaking changes.

  • packages/fusion-runtime/src/unifiedGraphManager.ts
  • packages/fusion-runtime/tests/polling.test.ts
  • packages/runtime/src/createGatewayRuntime.ts
  • packages/runtime/src/plugins/useRetryOnSchemaReload.ts
`**`: For all PRs, we would like to verify that a Linear iss...

**: For all PRs, we would like to verify that a Linear issue is linked. Check if there's a mention for "GW-*" in the PR description, and the us know when it's missing.

In most cases, when a PR adds a new functionality, we would like to make sure it has documentation in the corresponding console project.
Use the global knowledge feature to search for PRs in graphql-hive/console repository that adds documentation. Suggest to create a follow up issue to add the missing documentation.

  • packages/fusion-runtime/src/unifiedGraphManager.ts
  • packages/fusion-runtime/tests/polling.test.ts
  • packages/runtime/src/createGatewayRuntime.ts
  • e2e/graphos-polling/services/graphos.ts
  • packages/runtime/src/plugins/useRetryOnSchemaReload.ts
`e2e/**`: This directory includes end-to-end tests for the g...

e2e/**: This directory includes end-to-end tests for the gateway.
The examples directory is generated based on the code in this directory.

  • e2e/graphos-polling/services/graphos.ts
🪛 Biome (1.9.4)
packages/runtime/src/plugins/useRetryOnSchemaReload.ts

[error] 11-11: Don't use '{}' as a type.

Prefer explicitly define the object shape. '{}' means "any non-nullable value".

(lint/complexity/noBannedTypes)

⏰ Context from checks skipped due to timeout of 90000ms (29)
  • GitHub Check: Binary built on ubuntu-24.04-arm
  • GitHub Check: Binary built on windows-latest
  • GitHub Check: Binary built on macos-14
  • GitHub Check: Bun Docker image
  • GitHub Check: Binary built on macos-13
  • GitHub Check: Node Docker image
  • GitHub Check: Binary built on ubuntu-latest
  • GitHub Check: Bundle
  • GitHub Check: Benchmark / bun / 1000 items
  • GitHub Check: Build
  • GitHub Check: Lint
  • GitHub Check: Benchmark / bun / 100 items
  • GitHub Check: Benchmark / bun / 10 items
  • GitHub Check: Benchmark / node / 1000 items
  • GitHub Check: Benchmark / node / 100 items
  • GitHub Check: Benchmark / node / 10 items
  • GitHub Check: E2E / Bun Docker on Ubuntu
  • GitHub Check: E2E / Bun on Ubuntu
  • GitHub Check: E2E / Node Binary on Windows
  • GitHub Check: E2E / Node Binary on Ubuntu
  • GitHub Check: E2E / Node Docker on Ubuntu
  • GitHub Check: Leaks / Node v23
  • GitHub Check: E2E / Node 23 on Ubuntu
  • GitHub Check: Leaks / Node v22
  • GitHub Check: E2E / Node 22 on Ubuntu
  • GitHub Check: Leaks / Node v20
  • GitHub Check: E2E / Node 20 on Ubuntu
  • GitHub Check: Leaks / Node v18
  • GitHub Check: E2E / Node 18 on Ubuntu
🔇 Additional comments (20)
packages/runtime/src/plugins/useRetryOnSchemaReload.ts (4)

1-6: Clean imports with relevant dependencies.

The imports are logically organized and include all necessary dependencies for handling async iterable, maybe promises, and GraphQL execution results. The YogaInitialContext will be used for context casting during request handling.


7-13: Good plugin structure with type-safe context handling.

The plugin is defined as a generic function that accepts a type parameter for context, allowing it to integrate with various context types in the gateway. The WeakMap is an excellent choice for associating execution handlers with contexts as it avoids memory leaks.

🧰 Tools
🪛 Biome (1.9.4)

[error] 11-11: Don't use '{}' as a type.

Prefer explicitly define the object shape. '{}' means "any non-nullable value".

(lint/complexity/noBannedTypes)


14-23: Effective context and execution handler caching.

The onParams hook correctly stores the execution handler function in the WeakMap using the context as a key. This is a solid approach for preserving the execution context for potential retries.


24-38:

✅ Verification successful

Extend error handling for more schema reload scenarios.

Currently, the plugin only handles errors with the code 'SUBSCRIPTION_SCHEMA_RELOAD'. Based on the PR objectives which aim to enhance the retry mechanism for schema reloads during query execution, this should be extended to handle other schema reload error codes as well.


🏁 Script executed:

#!/bin/bash
# Search for all schema reload related error codes in the codebase

echo "Searching for schema reload related error codes..."
rg -i "SCHEMA_RELOAD" --type=ts

echo "Checking for error handlers related to schema reloads..."
rg -i "schema reload|reload.+schema" --type=ts -A 3 -B 3

Length of output: 5069


Schema Reload Error Handling – Current Implementation is Sufficient

After verifying the repository, it appears that the only schema reload error code in use is 'SUBSCRIPTION_SCHEMA_RELOAD'. The tests and other parts of the codebase (e.g., in packages/runtime/tests/subscriptions.test.ts and packages/fusion-runtime/src/unifiedGraphManager.ts) all rely on that single code. As such, the current logic in packages/runtime/src/plugins/useRetryOnSchemaReload.ts is consistent with the rest of the system.

  • If future PRs or requirements introduce additional schema reload error codes, we should update this handler accordingly.
  • For now, no changes are needed.
packages/runtime/src/createGatewayRuntime.ts (4)

101-101: Clean integration of the new retry plugin.

The import statement for useRetryOnSchemaReload is correctly added, ensuring the new functionality is available for use in the gateway runtime.


195-197: Well-defined schema replacement function.

The new replaceSchema function provides a clear mechanism for updating the unified graph schema. This lambda function is defined at the appropriate scope, ensuring it has access to the unifiedGraph variable.


690-693: Effective schema update handling in UnifiedGraphManager.

The implementation of onUnifiedGraphChange correctly updates the local schema and calls the replaceSchema function, ensuring consistency when the schema changes. This is crucial for the retry mechanism to work properly.


973-973: Strategic placement of the retry plugin in basePlugins.

The useRetryOnSchemaReload() plugin is correctly added to the basePlugins array, ensuring it's included in every gateway instance. Its position in the array is appropriate as it needs to be active for all requests.

packages/fusion-runtime/src/unifiedGraphManager.ts (7)

108-108: Clear interface extension for schema change notifications.

The onUnifiedGraphChange optional method is a well-designed addition to the UnifiedGraphManagerOptions interface. It provides a clean way to handle schema changes externally.


169-175: Improved error handling for polling failures.

The enhanced error handling now properly logs errors when polling the supergraph fails. This provides better visibility into issues that may occur during schema polling.


289-351: Streamlined schema update logic with proper notification.

The refactored handleLoadedUnifiedGraph method now correctly updates all relevant properties when a new schema is loaded and calls the onUnifiedGraphChange callback if provided. This ensures that all components are aware of schema changes.


336-336: Essential notification for schema changes.

This line is crucial as it notifies external components about schema changes by calling the onUnifiedGraphChange callback. This is the key connection point that enables the retry mechanism in the gateway runtime.


339-350: Clear error message for subscription schema reloads.

The error message for subscription schema reloads is clear and includes the appropriate code and HTTP status. This helps clients understand why their subscription was closed and allows the retry mechanism to identify these errors.


443-458: Consolidated resource cleanup in asyncDispose.

The asyncDispose method now handles all cleanup operations, including setting various properties to undefined. This is a cleaner approach to resource management compared to having separate cleanup methods.


461-473: Efficient utility for handling multiple disposables.

The new disposeAll function provides a clean way to dispose of multiple resources, making the code more maintainable. It correctly filters promises and handles both single and multiple promise cases.

packages/fusion-runtime/tests/polling.test.ts (5)

17-20: Enhanced imports for better async handling.

The import of handleMaybePromise from @whatwg-node/promise-helpers enables more streamlined handling of asynchronous operations in the tests.


62-62: Simplified mock function setup.

The disposeFn mock function is now defined more simply without the explicit mockResolvedValue(undefined) call, which is sufficient for testing purposes.


81-95: Refactored test helper for better error handling.

The getFetchedTimeOnComment function has been refactored to use handleMaybePromise for managing asynchronous operations. This approach provides better error handling and makes the code more readable.


97-119: Improved async handling in test helper.

The getFetchedTimeFromResolvers function now uses nested handleMaybePromise calls to handle the asynchronous operations, including the execution of GraphQL queries. This approach provides more robust error handling.


121-133: Streamlined comparison logic with better async flow.

The compareTimes function has been refactored to use handleMaybePromise for a cleaner async flow. This makes the test more robust and easier to understand.

Copy link
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

♻️ Duplicate comments (1)
packages/runtime/src/plugins/useRetryOnSchemaReload.ts (1)

27-29: ⚠️ Potential issue

Extend error handling to cover all schema reload scenarios, not just subscriptions

The current implementation only checks for errors with the code 'SUBSCRIPTION_SCHEMA_RELOAD', but based on the PR description, this plugin should handle schema reloads for all types of operations, not just subscriptions.

Consider updating the error checking logic to handle all schema reload error codes. For example:

-          (e) => e.extensions?.['code'] === 'SUBSCRIPTION_SCHEMA_RELOAD',
+          (e) => e.extensions?.['code'] === 'SCHEMA_RELOAD' || e.extensions?.['code'] === 'SUBSCRIPTION_SCHEMA_RELOAD',

This would ensure that both regular query schema reloads and subscription schema reloads are handled properly.

🧹 Nitpick comments (5)
e2e/graphos-polling/services/graphos.ts (4)

5-7: Consider potential concurrency issues with the global variable.

Storing supergraphSDL in a global variable may introduce concurrency risks when multiple requests are served simultaneously. If this is just for tests, it might be acceptable. Otherwise, consider scoping the variable more narrowly or storing it in a concurrent-safe data store.


9-47: Unused union types might be unnecessary.

Although the union RouterConfigResults supports FetchError and Unchanged, the resolver always returns RouterConfigResult. If these extra possibilities are no longer needed, consider removing them for clarity and maintainability.


53-59: Use string IDs for GraphQL consistency.

Date.now() returns a numeric timestamp, but GraphQL IDs are often treated as strings. Converting the timestamp to string ensures consistent type usage if your schema or clients expect string identifiers.

- id: Date.now(),
+ id: String(Date.now()),

74-78: Add error handling and ensure proper PR references & documentation.

  1. Consider adding basic error handling or logging for the server startup to help diagnose potential port binding errors.
  2. We don’t see a mention of a “GW-*” Linear issue in this PR. If relevant, please ensure proper linking.
  3. This new functionality may need documentation in the graphql-hive/console repository. Consider creating a follow-up issue if documentation is missing.
packages/runtime/src/plugins/useRetryOnSchemaReload.ts (1)

10-13: Avoid using '{}' as a type

The static analysis tool flagged this line because using {} as a type is generally discouraged. It means "any non-nullable value" rather than an empty object.

Consider using a more specific type:

  const execHandlerByContext = new WeakMap<
-    {},
+    Record<string, any>,
    () => MaybePromise<MaybeAsyncIterable<ExecutionResult>>
  >();
🧰 Tools
🪛 Biome (1.9.4)

[error] 11-11: Don't use '{}' as a type.

Prefer explicitly define the object shape. '{}' means "any non-nullable value".

(lint/complexity/noBannedTypes)

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 6f96142 and 3f027c2.

⛔ Files ignored due to path filters (1)
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (15)
  • .changeset/many-numbers-sell.md (1 hunks)
  • e2e/graphos-polling/graphos-polling.e2e.ts (1 hunks)
  • e2e/graphos-polling/package.json (1 hunks)
  • e2e/graphos-polling/services/graphos.ts (1 hunks)
  • e2e/graphos-polling/services/upstreamGood.ts (1 hunks)
  • e2e/graphos-polling/services/upstreamStuck.ts (1 hunks)
  • internal/e2e/src/example-setup.ts (1 hunks)
  • internal/e2e/src/tenv.ts (4 hunks)
  • packages/fusion-runtime/src/unifiedGraphManager.ts (4 hunks)
  • packages/fusion-runtime/tests/polling.test.ts (3 hunks)
  • packages/gateway/src/commands/supergraph.ts (1 hunks)
  • packages/runtime/src/createGatewayRuntime.ts (4 hunks)
  • packages/runtime/src/plugins/useRetryOnSchemaReload.ts (1 hunks)
  • packages/runtime/tests/schema-reload.test.ts (1 hunks)
  • packages/runtime/tests/subscriptions.test.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (11)
  • .changeset/many-numbers-sell.md
  • e2e/graphos-polling/package.json
  • e2e/graphos-polling/services/upstreamStuck.ts
  • packages/runtime/tests/subscriptions.test.ts
  • packages/gateway/src/commands/supergraph.ts
  • e2e/graphos-polling/services/upstreamGood.ts
  • internal/e2e/src/example-setup.ts
  • packages/runtime/tests/schema-reload.test.ts
  • packages/fusion-runtime/tests/polling.test.ts
  • e2e/graphos-polling/graphos-polling.e2e.ts
  • packages/fusion-runtime/src/unifiedGraphManager.ts
🧰 Additional context used
📓 Path-based instructions (3)
`**`: For all PRs, we would like to verify that a Linear iss...

**: For all PRs, we would like to verify that a Linear issue is linked. Check if there's a mention for "GW-*" in the PR description, and the us know when it's missing.

In most cases, when a PR adds a new functionality, we would like to make sure it has documentation in the corresponding console project.
Use the global knowledge feature to search for PRs in graphql-hive/console repository that adds documentation. Suggest to create a follow up issue to add the missing documentation.

  • internal/e2e/src/tenv.ts
  • packages/runtime/src/createGatewayRuntime.ts
  • e2e/graphos-polling/services/graphos.ts
  • packages/runtime/src/plugins/useRetryOnSchemaReload.ts
`packages/**`: In this directory we keep all packages releva...

packages/**: In this directory we keep all packages relevant to the gateway.

In most cases, when changes are made to the source code / dependencies in these directories, we also require to have a corresponding changeset file, created using yarn changeset with a full description on the changes with an example.
Also, when new features are added the packages, the changeset file should mention minor semver change. When a bug is fixed, patch needs to be used. The major bump is used for a PR that has breaking changes.

  • packages/runtime/src/createGatewayRuntime.ts
  • packages/runtime/src/plugins/useRetryOnSchemaReload.ts
`e2e/**`: This directory includes end-to-end tests for the g...

e2e/**: This directory includes end-to-end tests for the gateway.
The examples directory is generated based on the code in this directory.

  • e2e/graphos-polling/services/graphos.ts
🪛 Biome (1.9.4)
packages/runtime/src/plugins/useRetryOnSchemaReload.ts

[error] 11-11: Don't use '{}' as a type.

Prefer explicitly define the object shape. '{}' means "any non-nullable value".

(lint/complexity/noBannedTypes)

⏰ Context from checks skipped due to timeout of 90000ms (37)
  • GitHub Check: Examples / Convert operation-field-permissions
  • GitHub Check: Examples / Convert subscriptions-with-transforms
  • GitHub Check: Examples / Convert programmatic-batching
  • GitHub Check: Examples / Convert openapi-subscriptions
  • GitHub Check: Examples / Convert openapi-arg-rename
  • GitHub Check: Examples / Convert json-schema-subscriptions
  • GitHub Check: Examples / Convert interface-additional-resolvers
  • GitHub Check: Examples / Convert hmac-auth-https
  • GitHub Check: Examples / Convert apq-subgraphs
  • GitHub Check: Examples / Convert file-upload
  • GitHub Check: Examples / Convert federation-mixed
  • GitHub Check: Examples / Convert federation-example
  • GitHub Check: Examples / Convert extra-fields
  • GitHub Check: Binary built on ubuntu-24.04-arm
  • GitHub Check: Binary built on windows-latest
  • GitHub Check: Binary built on macos-14
  • GitHub Check: Bun Docker image
  • GitHub Check: Binary built on macos-13
  • GitHub Check: Node Docker image
  • GitHub Check: Binary built on ubuntu-latest
  • GitHub Check: E2E / Bun Docker on Ubuntu
  • GitHub Check: E2E / Node Binary on Windows
  • GitHub Check: E2E / Node Binary on Ubuntu
  • GitHub Check: E2E / Node Docker on Ubuntu
  • GitHub Check: E2E / Node 23 on Ubuntu
  • GitHub Check: Leaks / Node v23
  • GitHub Check: E2E / Node 22 on Ubuntu
  • GitHub Check: Leaks / Node v22
  • GitHub Check: E2E / Node 20 on Ubuntu
  • GitHub Check: Leaks / Node v20
  • GitHub Check: E2E / Node 18 on Ubuntu
  • GitHub Check: Leaks / Node v18
  • GitHub Check: Unit / Bun
  • GitHub Check: Benchmark / bun / 10 items
  • GitHub Check: Benchmark / node / 1000 items
  • GitHub Check: Benchmark / node / 100 items
  • GitHub Check: Benchmark / node / 10 items
🔇 Additional comments (9)
e2e/graphos-polling/services/graphos.ts (1)

62-66: LGTM!

The mutation logic is straightforward and clearly updates supergraphSDL.

internal/e2e/src/tenv.ts (4)

270-270: Interface method signature updated to return Compose object.

The return type for composeWithApollo was updated to match the actual implementation which returns a full Compose object instead of just a string. This change provides more control over the composed schema lifecycle.


383-383: Updated to destructure the object returned by composeWithApollo.

This update properly handles the new return type of composeWithApollo, extracting just the output property which is used to set the supergraph variable. This change ensures compatibility with the updated interface.


1-1057: Linear issue reference check for the PR.

Reviewing the PR objectives, I don't see a reference to a Linear issue (GW-*) in the PR description. This should be added to align with the team's workflow requirements.

This PR implements a feature to retry requests when schema reloads occur. Please ensure a Linear issue is linked in the PR description with the format "GW-*".

Additionally, since this appears to be a new functionality, documentation should be added to the corresponding console project.

🧰 Tools
🪛 Biome (1.9.4)

[error] 826-826: Avoid the use of spread (...) syntax on accumulators.

Spread syntax should be avoided on accumulators (like those in .reduce) because it causes a time complexity of O(n^2).
Consider methods such as .splice or .push instead.

(lint/performance/noAccumulatingSpread)


[error] 839-839: Avoid the use of spread (...) syntax on accumulators.

Spread syntax should be avoided on accumulators (like those in .reduce) because it causes a time complexity of O(n^2).
Consider methods such as .splice or .push instead.

(lint/performance/noAccumulatingSpread)


972-994:

❓ Verification inconclusive

Added proper resource cleanup for Apollo composition.

The updated implementation stores the introspectAndCompose instance rather than just extracting the supergraphSdl property. This allows for proper cleanup via the added [DisposableSymbols.asyncDispose] method. This change is significant because it:

  1. Returns a proper Compose object with all required properties
  2. Implements resource cleanup through the disposal method
  3. Prevents memory leaks by cleaning up the composition resources

The implementation aligns with the PR objective to enhance retry behavior during schema reloads, as proper resource cleanup is essential for reliable retries.


🏁 Script executed:

#!/bin/bash
# Check if the feature is tested in end-to-end tests

# Look for tests that might be exercising the schema reload retry
rg -l "schema.reload" --type ts internal/e2e/

Length of output: 45


Manual Verification: Confirm Schema Reload Test Coverage & Resource Cleanup

In file internal/e2e/src/tenv.ts (lines 972-994), the updated implementation now instantiates an IntrospectAndCompose object and retains it so that cleanup can be properly handled through the [DisposableSymbols.asyncDispose] method. This change:

  • Returns a Compose object with all the required properties.
  • Implements resource cleanup via the asynchronous disposal method.
  • Helps prevent potential memory leaks by ensuring resources are released properly during retries.

However, our initial search for tests explicitly exercising the schema reload behavior (using the term "schema.reload") didn’t produce any results. Please manually verify that the intended retry behavior – and the related cleanup mechanism – is covered by appropriate end-to-end tests, or update the test suite accordingly.

packages/runtime/src/createGatewayRuntime.ts (4)

101-101: LGTM: Import of new schema reload retry plugin

The new plugin import is correctly added.


195-197: LGTM: Well-implemented schema replacement callback

This implementation of replaceSchema properly updates the unifiedGraph variable when the schema changes.


690-693: LGTM: Appropriate handling of unified graph changes

The onUnifiedGraphChange callback correctly updates the schema and calls the replaceSchema callback, which ensures that components using the schema are properly updated when it changes.


973-973: LGTM: Schema reload retry plugin correctly added to base plugins

The useRetryOnSchemaReload plugin is correctly added to the base plugins array, ensuring it's applied to all requests.

Copy link
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: 1

🧹 Nitpick comments (1)
internal/e2e/src/tenv.ts (1)

985-1018: Consider extracting the logger implementation

The current implementation repeats similar logging code for different log levels (debug, error, info, warn). Consider extracting this into a reusable logger factory function to reduce code duplication.

+ function createLogger(stdout: string, stderr: string, stdboth: string, pipeLogs: boolean) {
+   return {
+     debug(msg: any) {
+       if (isDebug()) {
+         const line = inspect(msg) + '\n';
+         stdout += line;
+         stdboth += line;
+         if (pipeLogs) {
+           process.stdout.write(line);
+         }
+       }
+     },
+     error(msg: any) {
+       const line = inspect(msg) + '\n';
+       stderr += line;
+       stdboth += line;
+       if (pipeLogs) {
+         process.stderr.write(line);
+       }
+     },
+     info(msg: any) {
+       const line = inspect(msg) + '\n';
+       stdout += line;
+       stdboth += line;
+       if (pipeLogs) {
+         process.stdout.write(line);
+       }
+     },
+     warn(msg: any) {
+       const line = inspect(msg) + '\n';
+       stdout += line;
+       stdboth += line;
+       if (pipeLogs) {
+         process.stdout.write(line);
+       }
+     }
+   };
+ }
+
  let stderr = '';
  let stdout = '';
  let stdboth = '';

  let supergraphSdl: string;
  const introspectAndCompose = new IntrospectAndCompose({
    subgraphs,
-   logger: {
-     debug(msg) {
-       if (isDebug()) {
-         const line = inspect(msg) + '\n';
-         stdout += line;
-         stdboth += line;
-         if (pipeLogs) {
-           process.stdout.write(line);
-         }
-       }
-     },
-     error(msg) {
-       const line = inspect(msg) + '\n';
-       stderr += line;
-       stdboth += line;
-       if (pipeLogs) {
-         process.stderr.write(line);
-       }
-     },
-     info(msg) {
-       const line = inspect(msg) + '\n';
-       stdout += line;
-       stdboth += line;
-       if (pipeLogs) {
-         process.stdout.write(line);
-       }
-     },
-     warn(msg) {
-       const line = inspect(msg) + '\n';
-       stdout += line;
-       stdboth += line;
-       if (pipeLogs) {
-         process.stdout.write(line);
-       }
-     },
-   },
+   logger: createLogger(stdout, stderr, stdboth, pipeLogs),
  });
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between a005d81 and 52e59e5.

📒 Files selected for processing (7)
  • e2e/graphos-polling/gateway.config.ts (1 hunks)
  • e2e/graphos-polling/graphos-polling.e2e.ts (1 hunks)
  • e2e/graphos-polling/services/graphos.ts (1 hunks)
  • internal/e2e/src/example-setup.ts (1 hunks)
  • internal/e2e/src/tenv.ts (4 hunks)
  • packages/gateway/src/commands/supergraph.ts (4 hunks)
  • packages/runtime/src/getReportingPlugin.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • internal/e2e/src/example-setup.ts
  • e2e/graphos-polling/services/graphos.ts
  • packages/gateway/src/commands/supergraph.ts
🧰 Additional context used
📓 Path-based instructions (3)
`packages/**`: In this directory we keep all packages releva...

packages/**: In this directory we keep all packages relevant to the gateway.

In most cases, when changes are made to the source code / dependencies in these directories, we also require to have a corresponding changeset file, created using yarn changeset with a full description on the changes with an example.
Also, when new features are added the packages, the changeset file should mention minor semver change. When a bug is fixed, patch needs to be used. The major bump is used for a PR that has breaking changes.

  • packages/runtime/src/getReportingPlugin.ts
`**`: For all PRs, we would like to verify that a Linear iss...

**: For all PRs, we would like to verify that a Linear issue is linked. Check if there's a mention for "GW-*" in the PR description, and the us know when it's missing.

In most cases, when a PR adds a new functionality, we would like to make sure it has documentation in the corresponding console project.
Use the global knowledge feature to search for PRs in graphql-hive/console repository that adds documentation. Suggest to create a follow up issue to add the missing documentation.

  • packages/runtime/src/getReportingPlugin.ts
  • e2e/graphos-polling/graphos-polling.e2e.ts
  • e2e/graphos-polling/gateway.config.ts
  • internal/e2e/src/tenv.ts
`e2e/**`: This directory includes end-to-end tests for the g...

e2e/**: This directory includes end-to-end tests for the gateway.
The examples directory is generated based on the code in this directory.

  • e2e/graphos-polling/graphos-polling.e2e.ts
  • e2e/graphos-polling/gateway.config.ts
⏰ Context from checks skipped due to timeout of 90000ms (43)
  • GitHub Check: Examples / Convert operation-field-permissions
  • GitHub Check: Examples / Convert type-merging-batching
  • GitHub Check: Examples / Convert subscriptions-with-transforms
  • GitHub Check: Examples / Convert programmatic-batching
  • GitHub Check: Examples / Convert openapi-subscriptions
  • GitHub Check: Examples / Convert openapi-javascript-wiki
  • GitHub Check: Examples / Convert openapi-arg-rename
  • GitHub Check: Examples / Convert openapi-additional-resolvers
  • GitHub Check: Examples / Convert json-schema-subscriptions
  • GitHub Check: Examples / Convert interface-additional-resolvers
  • GitHub Check: Examples / Convert hmac-auth-https
  • GitHub Check: Examples / Convert federation-subscriptions-passthrough
  • GitHub Check: Examples / Convert apq-subgraphs
  • GitHub Check: Examples / Convert file-upload
  • GitHub Check: Examples / Convert federation-mixed
  • GitHub Check: Examples / Convert federation-example
  • GitHub Check: Examples / Convert extra-fields
  • GitHub Check: Binary built on ubuntu-24.04-arm
  • GitHub Check: Binary built on windows-latest
  • GitHub Check: Binary built on macos-14
  • GitHub Check: Binary built on macos-13
  • GitHub Check: Bun Docker image
  • GitHub Check: Binary built on ubuntu-latest
  • GitHub Check: Node Docker image
  • GitHub Check: E2E / Bun Docker on Ubuntu
  • GitHub Check: E2E / Bun on Ubuntu
  • GitHub Check: E2E / Node Binary on Windows
  • GitHub Check: E2E / Node Binary on Ubuntu
  • GitHub Check: E2E / Node Docker on Ubuntu
  • GitHub Check: E2E / Node 23 on Ubuntu
  • GitHub Check: E2E / Node 22 on Ubuntu
  • GitHub Check: E2E / Node 20 on Ubuntu
  • GitHub Check: Leaks / Node v23
  • GitHub Check: E2E / Node 18 on Ubuntu
  • GitHub Check: Leaks / Node v22
  • GitHub Check: Leaks / Node v20
  • GitHub Check: Benchmark / bun / 1000 items
  • GitHub Check: Benchmark / bun / 100 items
  • GitHub Check: Leaks / Node v18
  • GitHub Check: Benchmark / bun / 10 items
  • GitHub Check: Benchmark / node / 1000 items
  • GitHub Check: Benchmark / node / 100 items
  • GitHub Check: Benchmark / node / 10 items
🔇 Additional comments (6)
e2e/graphos-polling/gateway.config.ts (1)

1-27: Gateway configuration looks good

The gateway configuration is well-structured and properly sets up both supergraph and reporting sections using the defineConfig function from @graphql-hive/gateway. The code correctly handles different environment conditions for determining the uplinkHost.

e2e/graphos-polling/graphos-polling.e2e.ts (2)

16-88: Well-structured test for schema reload retry behavior

This test effectively validates the core functionality of the PR - ensuring the system retries requests when the schema reloads during query execution rather than throwing errors. The test first uses a "stuck" subgraph that never returns, then updates the schema to use a "good" subgraph while a request is in flight, verifying that the request is properly retried against the new schema.


8-14: Good cleanup of interval resources

The code properly cleans up the interval after tests complete, preventing memory leaks and potential interference with other tests.

internal/e2e/src/tenv.ts (3)

384-387: Updated function call to match new signature

The call to composeWithApollo has been properly updated to use the new parameter structure.


966-1060: Enhanced implementation of composeWithApollo

The implementation has been significantly expanded to include detailed logging, proper error handling, and a more structured return value. The method now correctly:

  1. Determines the appropriate hostname based on the gateway runner
  2. Sets up comprehensive logging for different levels (debug, error, info, warn)
  3. Creates a temporary file for the supergraph SDL
  4. Initializes the IntrospectAndCompose instance with proper handlers
  5. Returns a structured object with useful methods

This substantial improvement aligns with the PR's goal of enhancing the system's behavior when handling schema reloads.


271-271:

✅ Verification successful

API signature changed for composeWithApollo

The method signature has been updated to accept a structured ComposeOptions object and return a more comprehensive Compose result object, which is a good improvement for API clarity.


🏁 Script executed:

#!/bin/bash
# Check for any other usages of the composeWithApollo function to ensure all callers use the new signature
rg -A 3 "composeWithApollo\(" --type ts

Length of output: 1703


API Change for composeWithApollo Verified

The updated method now clearly accepts a structured ComposeOptions object and returns a comprehensive Compose result. Our shell script check confirmed that all instances—in files like internal/e2e/src/tenv.ts, internal/e2e/src/example-setup.ts, and the graphos polling tests—are using the new signature (with consistent destructuring and either an output or result property being accessed). This confirms the intended improvement for API clarity.

Copy link
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: 2

🧹 Nitpick comments (3)
e2e/graphos-polling/graphos-polling.e2e.ts (3)

28-45: Add error checking for schema push operations.

The pushSchema function doesn't check if the operation was successful. Consider adding error handling to ensure the test fails appropriately if the schema update fails.

function pushSchema(schema: string) {
-  return fetch(`${hostname}:${graphos.port}/graphql`, {
+  return fetch(`${hostname}:${graphos.port}/graphql`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      query: /* GraphQL */ `
        mutation SetSupergraphSDL($sdl: String!) {
          setSupergraphSDL(sdl: $sdl)
        }
      `,
      variables: {
        sdl: schema,
      },
    }),
+  }).then(async response => {
+    const result = await response.json();
+    if (!response.ok || result.errors) {
+      throw new Error(`Failed to push schema: ${JSON.stringify(result.errors || 'Unknown error')}`);
+    }
+    return result;
  });
}

59-67: Consider adding a timeout to the interval.

The interval is set to execute queries every 100ms without an upper bound, which could lead to resource exhaustion if the test runs for too long. Consider adding a timeout or maximum number of attempts.

+ let attempts = 0;
+ const MAX_ATTEMPTS = 100; // 10 seconds total
  interval = setInterval(() => {
+   if (attempts >= MAX_ATTEMPTS) {
+     clearInterval(interval!);
+     interval = undefined;
+     console.warn('Max attempts reached for keeping gateway warm');
+     return;
+   }
+   attempts++;
    gw.execute({
      query: /* GraphQL */ `
        {
          __typename
        }
      `,
    });
  }, 100);

84-87: Verify retry behavior more explicitly.

The test checks that both services were called but doesn't directly verify that a retry occurred due to the schema reload. Consider adding assertions to verify the specific retry mechanism.

  const upstreamStuckStd = upstreamStuck.getStd('both');
  expect(upstreamStuckStd).toContain('foo on upstreamStuck');
  const upstreamGoodStd = upstreamGood.getStd('both');
  expect(upstreamGoodStd).toContain('foo on upstreamGood');
+ // Verify retry occurred by checking logs or metrics
+ // For example, if your gateway logs retries:
+ const gatewayStd = gw.getStd ? gw.getStd('both') : '';
+ expect(gatewayStd).toContain('Retrying request due to schema reload');
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 52e59e5 and 597c831.

📒 Files selected for processing (4)
  • e2e/graphos-polling/graphos-polling.e2e.ts (1 hunks)
  • e2e/graphos-polling/services/upstreamGood.ts (1 hunks)
  • e2e/graphos-polling/services/upstreamStuck.ts (1 hunks)
  • packages/runtime/src/getReportingPlugin.ts (0 hunks)
💤 Files with no reviewable changes (1)
  • packages/runtime/src/getReportingPlugin.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • e2e/graphos-polling/services/upstreamStuck.ts
  • e2e/graphos-polling/services/upstreamGood.ts
🧰 Additional context used
📓 Path-based instructions (2)
`e2e/**`: This directory includes end-to-end tests for the g...

e2e/**: This directory includes end-to-end tests for the gateway.
The examples directory is generated based on the code in this directory.

  • e2e/graphos-polling/graphos-polling.e2e.ts
`**`: For all PRs, we would like to verify that a Linear iss...

**: For all PRs, we would like to verify that a Linear issue is linked. Check if there's a mention for "GW-*" in the PR description, and the us know when it's missing.

In most cases, when a PR adds a new functionality, we would like to make sure it has documentation in the corresponding console project.
Use the global knowledge feature to search for PRs in graphql-hive/console repository that adds documentation. Suggest to create a follow up issue to add the missing documentation.

  • e2e/graphos-polling/graphos-polling.e2e.ts
⏰ Context from checks skipped due to timeout of 90000ms (44)
  • GitHub Check: Examples / Convert operation-field-permissions
  • GitHub Check: Examples / Convert type-merging-batching
  • GitHub Check: Examples / Convert subscriptions-with-transforms
  • GitHub Check: Examples / Convert programmatic-batching
  • GitHub Check: Examples / Convert openapi-subscriptions
  • GitHub Check: Examples / Convert openapi-javascript-wiki
  • GitHub Check: Examples / Convert openapi-arg-rename
  • GitHub Check: Examples / Convert openapi-additional-resolvers
  • GitHub Check: Examples / Convert json-schema-subscriptions
  • GitHub Check: Examples / Convert interface-additional-resolvers
  • GitHub Check: Examples / Convert hmac-auth-https
  • GitHub Check: Examples / Convert federation-subscriptions-passthrough
  • GitHub Check: Examples / Convert apq-subgraphs
  • GitHub Check: Examples / Convert file-upload
  • GitHub Check: Examples / Convert federation-mixed
  • GitHub Check: Examples / Convert federation-example
  • GitHub Check: Examples / Convert extra-fields
  • GitHub Check: Binary built on ubuntu-24.04-arm
  • GitHub Check: Binary built on windows-latest
  • GitHub Check: Binary built on macos-14
  • GitHub Check: Binary built on macos-13
  • GitHub Check: Binary built on ubuntu-latest
  • GitHub Check: Bun Docker image
  • GitHub Check: Node Docker image
  • GitHub Check: E2E / Bun Docker on Ubuntu
  • GitHub Check: E2E / Bun on Ubuntu
  • GitHub Check: E2E / Node Binary on Windows
  • GitHub Check: E2E / Node Binary on Ubuntu
  • GitHub Check: E2E / Node Docker on Ubuntu
  • GitHub Check: E2E / Node 23 on Ubuntu
  • GitHub Check: E2E / Node 22 on Ubuntu
  • GitHub Check: E2E / Node 20 on Ubuntu
  • GitHub Check: E2E / Node 18 on Ubuntu
  • GitHub Check: Leaks / Node v23
  • GitHub Check: Leaks / Node v22
  • GitHub Check: Leaks / Node v20
  • GitHub Check: Leaks / Node v18
  • GitHub Check: Benchmark / bun / 1000 items
  • GitHub Check: Bundle
  • GitHub Check: Benchmark / bun / 100 items
  • GitHub Check: Benchmark / bun / 10 items
  • GitHub Check: Benchmark / node / 1000 items
  • GitHub Check: Benchmark / node / 100 items
  • GitHub Check: Benchmark / node / 10 items
🔇 Additional comments (3)
e2e/graphos-polling/graphos-polling.e2e.ts (3)

10-14: Good cleanup handling in the afterAll block.

Properly cleaning up intervals is crucial to prevent memory leaks and interference with other tests.


16-20: Clear test scenario documentation.

The comment clearly explains the test scenario, which is good for readability and maintenance.


1-88: Verify Linear issue is linked.

I couldn't find a mention of a "GW-*" issue in the PR description. According to the coding guidelines, all PRs should have a linked Linear issue.

Please check if there's a Linear issue linked to this PR and add it to the description if it's missing.

Copy link
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: 1

🧹 Nitpick comments (1)
e2e/graphos-polling/services/upstream_good.ts (1)

1-31: Clean implementation of a properly functioning test service.

This "good" upstream service is well-implemented as a counterpart to the stuck service, returning a simple 'bar' response. The pair of services create an ideal testing environment for the schema reload retry mechanism.

For consistency between files, you might consider using the same function style for resolvers as in upstream_stuck.ts:

-          foo() {
+          foo: () => {

Both styles work fine, but maintaining the same style across similar files can improve readability and maintenance.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 597c831 and 3b6d5ed.

📒 Files selected for processing (2)
  • e2e/graphos-polling/services/upstream_good.ts (1 hunks)
  • e2e/graphos-polling/services/upstream_stuck.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
`e2e/**`: This directory includes end-to-end tests for the g...

e2e/**: This directory includes end-to-end tests for the gateway.
The examples directory is generated based on the code in this directory.

  • e2e/graphos-polling/services/upstream_good.ts
  • e2e/graphos-polling/services/upstream_stuck.ts
`**`: For all PRs, we would like to verify that a Linear iss...

**: For all PRs, we would like to verify that a Linear issue is linked. Check if there's a mention for "GW-*" in the PR description, and the us know when it's missing.

In most cases, when a PR adds a new functionality, we would like to make sure it has documentation in the corresponding console project.
Use the global knowledge feature to search for PRs in graphql-hive/console repository that adds documentation. Suggest to create a follow up issue to add the missing documentation.

  • e2e/graphos-polling/services/upstream_good.ts
  • e2e/graphos-polling/services/upstream_stuck.ts
⏰ Context from checks skipped due to timeout of 90000ms (23)
  • GitHub Check: Unit / Bun
  • GitHub Check: Unit / Node v20
  • GitHub Check: E2E / Bun Docker on Ubuntu
  • GitHub Check: E2E / Bun on Ubuntu
  • GitHub Check: Leaks / Node v23
  • GitHub Check: Leaks / Node v22
  • GitHub Check: E2E / Node Binary on Ubuntu
  • GitHub Check: Leaks / Node v20
  • GitHub Check: E2E / Node Docker on Ubuntu
  • GitHub Check: Benchmark / bun / 1000 items
  • GitHub Check: Leaks / Node v18
  • GitHub Check: E2E / Node 23 on Ubuntu
  • GitHub Check: Benchmark / bun / 100 items
  • GitHub Check: E2E / Node 22 on Ubuntu
  • GitHub Check: Benchmark / bun / 10 items
  • GitHub Check: Benchmark / node / 1000 items
  • GitHub Check: E2E / Node 20 on Ubuntu
  • GitHub Check: Bundle
  • GitHub Check: Benchmark / node / 100 items
  • GitHub Check: E2E / Node 18 on Ubuntu
  • GitHub Check: Benchmark / node / 10 items
  • GitHub Check: Build
  • GitHub Check: Analyze (javascript-typescript)

Copy link
Member

@enisdenjo enisdenjo left a comment

Choose a reason for hiding this comment

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

LGTM!

@ardatan ardatan enabled auto-merge (squash) March 14, 2025 09:04
@ardatan ardatan force-pushed the retry branch 2 times, most recently from ac6224e to 7defbda Compare March 14, 2025 09:24
@ardatan ardatan merged commit 115a1f1 into main Mar 14, 2025
63 checks passed
@ardatan ardatan deleted the retry branch March 14, 2025 09:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants