graphql-mesh icon indicating copy to clipboard operation
graphql-mesh copied to clipboard

Hive Gateway subscriptons not working

Open klys-equinix opened this issue 1 year ago • 7 comments

Issue workflow progress

Progress of the issue based on the Contributor Workflow

Make sure to fork this template and run yarn generate in the terminal.

Please make sure Mesh package versions under package.json matches yours.

  • [ ] 2. A failing test has been provided
  • [ ] 3. A local solution has been provided
  • [ ] 4. A pull request is pending review

Describe the bug

Graphql subscriptions do not work. If i try to run the subscription through GraphiQL, the response is 404 Screenshot 2024-09-12 at 10 09 13

The OpenTelemetry logs are as follows:

{
resource: {
attributes: {
'service.name': 'Gateway',
'telemetry.sdk.language': 'nodejs',
'telemetry.sdk.name': 'opentelemetry',
'telemetry.sdk.version': '1.25.1',
'process.pid': 6,
'process.executable.name': 'node',
'process.executable.path': '/usr/local/bin/node',
'process.command_args': [ '/usr/local/bin/node', '/serve/bin.mjs', 'supergraph' ],
'process.runtime.version': '22.8.0',
'process.runtime.name': 'nodejs',
'process.runtime.description': 'Node.js',
'process.command': '/serve/bin.mjs',
'process.owner': 'node',
'host.name': 'hive-gateway-external-66984f7fd-5w5hb',
'host.arch': 'amd64'
}
},
instrumentationScope: { name: 'gateway', version: undefined, schemaUrl: undefined },
traceId: '5a5a8607eaa73a972e9cf13cb7f104e7',
parentId: undefined,
traceState: undefined,
name: 'GET /gateway/graphql',
id: 'a2a1816dfb7b25ec',
kind: 1,
timestamp: 1726128168069000,
duration: 2460.951,
attributes: {
'http.method': 'GET',
'http.url': 'http://localhost/gateway/graphql?query=subscription+test%7BinventoryEvents%7B...on+CabinetStatusChangedEvent%7BeventId+cabinetId+previousStatusId+currentStatusId%7D...on+CageStatusChangedEvent%7BeventId+cageId+previousStatusId+currentStatusId%7D%7D%7D&operationName=test&extensions=%7B%7D',
'http.route': '/gateway/graphql',
'http.scheme': 'http:',
'net.host.name': 'localhost',
'http.host': 'localhost',
'http.client_ip': '10.249.0.4',
'http.user_agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:130.0) Gecko/20100101 Firefox/130.0',
'http.status_code': 404
},
status: { code: 2, message: 'Not Found' },
events: [],
links: []
} 

Queries for the same subgraph that provides this subscription work correctly.
Subscribing directly to subgraph works correctly


**To Reproduce** Steps to reproduce the behavior:

Run Hive Gateway with at least one subgraph implementing subscriptions using websocket transport.
Configure Hive Gateway with endpoint:

gateway.config.ts: | import {defineConfig, type WSTransportOptions, createStdoutExporter} from '@graphql-hive/gateway'

export const gatewayConfig = defineConfig({
  transportEntries: {
    // use "*.http" to apply options to all subgraphs with HTTP
    '*.http': {
      options: {
        subscriptions: {
          kind: 'ws',
          location: '/graphql'
        } satisfies WSTransportOptions
      }
    }
  },
  openTelemetry: {
    exporters: [
      // A simple output to the console.
      // You can add more exporters here, please see documentation below for more examples.
      createStdoutExporter()
    ],
    spans: {
      http: true, // Whether to track the HTTP request/response
      graphqlParse: true, // Whether to track the GraphQL parse phase
      graphqlValidate: true, // Whether to track the GraphQL validate phase
      graphqlExecute: true, // Whether to track the GraphQL execute phase
      subgraphExecute: true, // Whether to track the subgraph execution phase
      upstreamFetch: true // Whether to track the upstream HTTP requests
    }
  }
})

**Expected behavior**

Subscriptions work correctly

**Environment:**

- OS:
- Hive Gateway Docker


klys-equinix avatar Sep 12 '24 08:09 klys-equinix

Could you give more details about your subgraphs? Do they use graphql-ws protocol? Or maybe they use the legacy subscriptions-transport-ws?

ardatan avatar Sep 12 '24 12:09 ardatan

There is only one subgraph serving subscriptions. It is based on graphql-ws protocol

https://docs.spring.io/spring-graphql/reference/transports.html#server.transports.websocket

But it seems like the gateway is not even trying to call it

klys-equinix avatar Sep 12 '24 13:09 klys-equinix

Have you tried to make the HTTP request with curl or some other http client?

ardatan avatar Sep 12 '24 14:09 ardatan

I tried making a request with Postman GraphQL client. There is says that gateway responded with incorrect response code 200 instead of 101 Screenshot 2024-09-12 at 18 23 45

Here are the logs from this request

{ resource: { attributes: { 'service.name': 'Gateway', 'telemetry.sdk.language': 'nodejs', 'telemetry.sdk.name': 'opentelemetry', 'telemetry.sdk.version': '1.25.1', 'process.pid': 6, 'process.executable.name': 'node', 'process.executable.path': '/usr/local/bin/node', 'process.command_args': [ '/usr/local/bin/node', '/serve/bin.mjs', 'supergraph' ], 'process.runtime.version': '22.8.0', 'process.runtime.name': 'nodejs', 'process.runtime.description': 'Node.js', 'process.command': '/serve/bin.mjs', 'process.owner': 'node', 'host.name': 'hive-gateway-external-7664cc5d55-89g5m', 'host.arch': 'amd64' } }, instrumentationScope: { name: 'gateway', version: undefined, schemaUrl: undefined }, traceId: '4fce12dacd20a8c23d04f77f0cdddbf9', parentId: undefined, traceState: undefined, name: 'GET /gateway/graphql', id: 'c16e61a8e3b4aaaf', kind: 1, timestamp: 1726157965615000, duration: 732.977, attributes: { 'http.method': 'GET', 'http.url': 'http://localhost/gateway/graphql', 'http.route': '/gateway/graphql', 'http.scheme': 'http:', 'net.host.name': 'localhost', 'http.host': 'localhost', 'http.client_ip': '10.249.0.4', 'http.user_agent': 'PostmanClient/undefined (AppId=6217ee3f-4ef9-4f3d-b10a-c0582107b1ea)', 'http.status_code': 200 }, status: { code: 1, message: undefined }, events: [], links: [] }

klys-equinix avatar Sep 12 '24 16:09 klys-equinix

Can you give me an example of correct curl for querying subscription on gateway?

klys-equinix avatar Sep 12 '24 16:09 klys-equinix

curl 'http://localhost:4000/graphql' \
  -H 'accept: text/event-stream' \
  -H 'content-type: application/json' \
  --data-raw '{"query":"subscription OnProductPriceChanged { productPriceChanged { name price reviews { score } } }","operationName":"OnProductPriceChanged"}'

You can initiate an SSE connection as in here with curl.

Regarding the error in the screenshots you shared above; In there, you are trying to connect the gateway via WebSockets not SSE. We only support the actively developed graphql-ws only not deprecated subscriptions-transport-ws . I am not sure which one Postman uses there.

ardatan avatar Sep 12 '24 17:09 ardatan

Hi, I tried forming the request like in the curl you described. This resulted in error:

event: next
data: {"errors":[{"message":"Cannot find package '@graphql-mesh/transport-ws' imported from /node_modules/.chunk/createGatewayRuntime-DfdVdZl2.mjs","locations":[{"line":1,"column":20}],"path":["inventoryEvents"]}]}

event: complete
data:

And in the logs:

[2024-09-13T09:21:43.876Z] DEBUG vdc-inventory-service - 430ed7d622f261c84c120254f2868472 subgraph-execute {
query: 'subscription test2{inventoryEvents{__typename ...on CabinetStatusChangedEvent{eventId}}}',
variables: {}
}
[2024-09-13T09:21:43.876Z] DEBUG Loading transport "ws" for subgraph vdc-inventory-service
[2024-09-13T09:21:43.877Z] HOOKS Trying default resolve for "@graphql-mesh/transport-ws"
[2024-09-13T09:21:43.879Z] DEBUG Processing GraphQL Parameters done.
[2024-09-13T09:21:43.878Z] HOOKS Trying default resolve for "@graphql-mesh/transport-ws" failed; trying alternatives
[2024-09-13T09:21:43.878Z] HOOKS Trying "@graphql-mesh/transport-ws.ts" 

This likely means two things:

  1. The docker image is missing the transport-ws package
  2. The GraphiQL provided with the Gateway is not compatible with how the Gateway handles subscriptions

klys-equinix avatar Sep 13 '24 09:09 klys-equinix