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

Improvements on GraphOS and Fastify integration #946

Open
wants to merge 11 commits into
base: main
Choose a base branch
from

Conversation

ardatan
Copy link
Member

@ardatan ardatan commented Mar 26, 2025

Related GW-270

Documentation -> graphql-hive/console#6663

Fixes

  • Fails when the fetcher returns an empty result. Previously even if fetcher returns undefined, the runtime was trying to handle the result then fails with a cryptic error

Improvements

  • Simplify and make readable the logs printed by the readiness checks, now it uses readiness title and prints passes or fails with errors if present

New Features

Pino integration (also helpful for Fastify integration);

import { defineConfig } from '@graphql-hive/gateway';
import pino from 'pino';
import { createLoggerFromPino } from '@graphql-hive/logger-pino';

export const gatewayConfig = defineConfig({
   logging: createLoggerFromPino(pino({ level: 'info' })),
});

Request ID configuration (helpful for Fastify integration)

By default, first Hive Gateway was checking if x-request-id exists in the HTTP headers, then generates and sets a new one.
And this can be disabled by setting requestId to false in the gatewayConfig.

Now you can configure the request ID generation by providing a function to the requestId field in the gatewayConfig (or inherit from the framework you use).
And you can also rename the header name by setting the headerName field in the gatewayConfig.

import { defineConfig } from '@graphql-hive/gateway';

export const gatewayConfig = defineConfig({
    requestId: {
        headerName: 'x-request-id',
        generateRequestId({ request, context, fetchAPI }) {
            return fetchAPI.crypto.randomUUID();
        }
    }
})

This is useful with Fastify because it handles the request ID generation and propagation by itself.

const requestIdHeader = 'x-guild-request-id';

const app = fastify({
  /** ... */
  requestIdHeader,
  // Align with Hive Gateway's request id log label
  requestIdLogLabel: 'requestId',
  genReqId(req) {
    if (req.headers[requestIdHeader]) {
      return req.headers[requestIdHeader].toString();
    }
    return crypto.randomUUID();
  },
});

const gateway = createGateway({
    /** ... */
    requestId: {
      headerName: requestIdHeader,
      generateRequestId({ request, context, fetchAPI }) {
        return request.id;
      }
    }
});

New Fastify Recipe

import fastify, { type FastifyReply, type FastifyRequest } from 'fastify'
import { createGatewayRuntime } from '@graphql-hive/gateway-runtime'
import { createLoggerFromPino } from '@graphql-hive/logger-pino'

// Request ID header used for tracking requests
const requestIdHeader = 'x-request-id'

// This is the fastify instance you have created
const app = fastify({
  logger: true,
  // Use our custom request id header
  requestIdHeader,
  // Align with Hive Gateway's request id log label
  requestIdLogLabel: 'requestId',
  // Check the header first, then generate a new one if not found
  genReqId: (req): string =>
    req.headers[requestIdHeader]?.toString() || gw.fetchAPI.crypto.randomUUID()
})

// This will allow us to access Fastify request and reply objects in the gateway
interface FastifyContext {
  req: FastifyRequest
  reply: FastifyReply
}

const gateway = createGatewayRuntime<FastifyContext>({
  // Integrate Fastify's logger / Pino with the gateway logger
  logging: createLoggerFromPino(app.log),
  // Align with Fastify
  requestId: {
    // Use the same header name as Fastify
    headerName: requestIdHeader,
    // Use the request id from Fastify (see `FastifyContext`)
    generateRequestId: ({ context }) => context.req.id
  },
  // Point to the supergraph
  supergraph: './supergraph.graphql'
})

// Bind the gateway to Fastify
app.route({
  // "*" is recommendeded in order to handle landing page, readiness and other related endpoints
  url: '*',
  method: ['GET', 'POST', 'OPTIONS'],
  // Connect the gateway to Fastify route
  handler: (req, reply) => gateway.handleNodeRequestAndResponse(req, reply, { req, reply })
})

const port = 4000

app.listen({ port, host: '0.0.0.0' }, err => {
  if (err) {
    console.error('Error starting gateway', err)
    process.exit(1)
  }
  console.log(`Gateway listening on port ${port}`)
})

@ardatan ardatan force-pushed the improvements-graphos branch from d5209eb to 3eda996 Compare March 26, 2025 14:22
@theguild-bot
Copy link
Collaborator

theguild-bot commented Mar 26, 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-tools/batch-delegate 9.0.35-alpha-da3ad60bd5595c273b81e55eea65bde564632356 npm ↗︎ unpkg ↗︎
@graphql-tools/delegate 10.2.17-alpha-da3ad60bd5595c273b81e55eea65bde564632356 npm ↗︎ unpkg ↗︎
@graphql-tools/federation 3.2.0-alpha-da3ad60bd5595c273b81e55eea65bde564632356 npm ↗︎ unpkg ↗︎
@graphql-mesh/fusion-runtime 0.11.9-alpha-da3ad60bd5595c273b81e55eea65bde564632356 npm ↗︎ unpkg ↗︎
@graphql-hive/gateway 1.13.5-alpha-da3ad60bd5595c273b81e55eea65bde564632356 npm ↗︎ unpkg ↗︎
@graphql-hive/logger-json 0.0.4-alpha-da3ad60bd5595c273b81e55eea65bde564632356 npm ↗︎ unpkg ↗︎
@graphql-hive/logger-pino 1.0.0-alpha-da3ad60bd5595c273b81e55eea65bde564632356 npm ↗︎ unpkg ↗︎
@graphql-hive/nestjs 1.0.9-alpha-da3ad60bd5595c273b81e55eea65bde564632356 npm ↗︎ unpkg ↗︎
@graphql-hive/plugin-aws-sigv4 1.0.6-alpha-da3ad60bd5595c273b81e55eea65bde564632356 npm ↗︎ unpkg ↗︎
@graphql-mesh/hmac-upstream-signature 1.2.26-alpha-da3ad60bd5595c273b81e55eea65bde564632356 npm ↗︎ unpkg ↗︎
@graphql-mesh/plugin-opentelemetry 1.3.53-alpha-da3ad60bd5595c273b81e55eea65bde564632356 npm ↗︎ unpkg ↗︎
@graphql-mesh/plugin-prometheus 1.3.41-alpha-da3ad60bd5595c273b81e55eea65bde564632356 npm ↗︎ unpkg ↗︎
@graphql-hive/gateway-runtime 1.7.0-alpha-da3ad60bd5595c273b81e55eea65bde564632356 npm ↗︎ unpkg ↗︎
@graphql-tools/stitch 9.4.22-alpha-da3ad60bd5595c273b81e55eea65bde564632356 npm ↗︎ unpkg ↗︎
@graphql-tools/stitching-directives 3.1.32-alpha-da3ad60bd5595c273b81e55eea65bde564632356 npm ↗︎ unpkg ↗︎
@graphql-mesh/transport-common 0.7.34-alpha-da3ad60bd5595c273b81e55eea65bde564632356 npm ↗︎ unpkg ↗︎
@graphql-mesh/transport-http 0.6.39-alpha-da3ad60bd5595c273b81e55eea65bde564632356 npm ↗︎ unpkg ↗︎
@graphql-mesh/transport-http-callback 0.5.26-alpha-da3ad60bd5595c273b81e55eea65bde564632356 npm ↗︎ unpkg ↗︎
@graphql-mesh/transport-ws 1.0.9-alpha-da3ad60bd5595c273b81e55eea65bde564632356 npm ↗︎ unpkg ↗︎
@graphql-tools/wrap 10.0.35-alpha-da3ad60bd5595c273b81e55eea65bde564632356 npm ↗︎ unpkg ↗︎

@theguild-bot
Copy link
Collaborator

theguild-bot commented Mar 26, 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 26, 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 26, 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 26, 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.13.5-alpha-da3ad60bd5595c273b81e55eea65bde564632356

@theguild-bot
Copy link
Collaborator

theguild-bot commented Mar 26, 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.13.5-alpha-da3ad60bd5595c273b81e55eea65bde564632356-bun

@theguild-bot
Copy link
Collaborator

theguild-bot commented Mar 26, 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 26, 2025

🚀 Snapshot Release (Binary for Windows-X64)

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

Download

@ardatan ardatan force-pushed the improvements-graphos branch 3 times, most recently from 6380a06 to 924921c Compare March 27, 2025 10:22
@ardatan ardatan marked this pull request as ready for review March 27, 2025 12:17
@Copilot Copilot bot review requested due to automatic review settings March 27, 2025 12:17
Copy link

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR improves the GraphOS and Fastify integration by fixing a bug when the fetcher returns an empty result, enhancing log readability, and adding support for Pino logging and flexible request ID configuration.

  • Fix error when fetcher returns an empty result
  • Improve log output for readiness checks
  • Introduce new Pino logging integration and configurable request IDs

Reviewed Changes

Copilot reviewed 49 out of 50 changed files in this pull request and generated no comments.

File Description
e2e/graphos-polling/graphos-polling.e2e.ts Updated the test harness to use Fastify endpoints and fetch-based requests for readiness and GraphQL queries
e2e/graphos-polling/gateway.config.ts Removed the configuration file in favor of inline configurations
.changeset/*.md Added changeset documentation for various fixes, improvements, and dependency updates
Files not reviewed (1)
  • e2e/graphos-polling/package.json: Language not supported
Comments suppressed due to low confidence (1)

e2e/graphos-polling/graphos-polling.e2e.ts:87

  • Consider adding an assertion on the readiness endpoint's response to ensure it meets expected behavior, which would enhance the test coverage of the new readiness checks.
const result$ = fetch(`http://0.0.0.0:${gw.port}/graphql`, {

@ardatan ardatan requested a review from Copilot March 27, 2025 12:17
Copy link

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR improves GraphOS and Fastify integration with better error handling for empty fetcher results, simplified log readability for readiness checks, and introduces new logging and request ID configuration capabilities.

  • Fixes crash when fetcher returns an empty result
  • Improves log readability in readiness checks
  • Adds Pino logging and flexible request ID configuration

Reviewed Changes

Copilot reviewed 49 out of 50 changed files in this pull request and generated no comments.

File Description
e2e/graphos-polling/graphos-polling.e2e.ts Updated polling test with refined gateway creation and use of fetch for readiness and GraphQL endpoints
e2e/graphos-polling/gateway.config.ts Removed gateway configuration file, likely replaced by new configuration approaches
.changeset/* Updated changesets summarizing the fixes, improvements, and dependency updates
Files not reviewed (1)
  • e2e/graphos-polling/package.json: Language not supported
Comments suppressed due to low confidence (1)

e2e/graphos-polling/graphos-polling.e2e.ts:87

  • [nitpick] The variable name 'result$' suggests an observable stream while it holds a Promise; consider renaming it (e.g., 'graphqlResult') to better reflect its asynchronous nature.
const result$ = fetch(`http://0.0.0.0:${gw.port}/graphql`, {

@ardatan ardatan force-pushed the improvements-graphos branch 6 times, most recently from c2b9317 to b82d9c6 Compare March 28, 2025 14:04
Comment on lines +45 to +52
let requestLogger = logger;
const requestId = requestIdByRequest.get(request);
if (requestId) {
requestLogger = logger.child({ requestId });
}
requestLogger.info(
'The operation has been aborted after the supergraph schema reloaded, retrying the operation...',
);
Copy link
Collaborator

Choose a reason for hiding this comment

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

I suppose that this a temporary workaround waiting for the new Logging system ?

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.

3 participants