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

How to set the server timeout

Open kv-pawar opened this issue 4 years ago • 3 comments

Hello,

I am using graphql-yoga to run my graphql service. What is the default timeout to graphql-yoga server? How can I set the maximum timeout on the server level?

Can someone help me here? Following is the code I am using.

const { GraphQLServer } = require('graphql-yoga');

const server = new GraphQLServer({
  schema,
  context: request => ({ ...request }),
  middleware: [loggingMiddleware]
})

const options = {
  port: 8050,
  endpoint: xyzService
}

server.start(options, ({ port, endpoint }) =>
  console.log(
    `Server started, listening on port ${port}${endpoint} for incoming requests.`,
  ),
)

kv-pawar avatar Jun 24 '20 08:06 kv-pawar

Do we have any resolution on it, I see graphql-yoga uses express-js internally, but how can I update the timeout of the server call.

We have a call to the view table which takes up to 5 mins runnings on the Dbeaver itself because of 5 million+ data rows. GraphQL-yoga query takes 2m as the default timeout. Is there any way we can update it?

AndroConsis avatar Aug 14 '20 04:08 AndroConsis

I also had issues with the 2 minute timeout so I forked the repo and added a timeout option. It doesn't look like graphql-yoga is actively maintained anymore so I shouldn't lose much by using a forked version and maintaining it myself.

If it wasn't for me using Prisma 1 with prisma-binding, I'd just switch to apollo-server-express, where it's easy to add a timeout

const server = new ApolloServer({ typeDefs, resolvers });
 
const app = express();
server.applyMiddleware({ app });
 
app.listen({ port: 4000 }, () =>
  console.log(`🚀 Server ready at http://localhost:4000${server.graphqlPath}`)
).setTimeout(1000*60*10)

This, however, breaks all my field aliases on my prisma resolvers and would force me to rewrite all of my middleware functions for my resolvers.

cotterjd avatar Oct 29 '20 16:10 cotterjd

You can increase the express timeout in graphql-yoga like so:

const server = new GraphQLServer({ typeDefs, resolvers });
server.start(() => console.log('Server is running on localhost:4000'))
  .then(s => s.setTimeout(5 * 60 * 1000)); // 5 minutes

In this case s is the instance of a regular node HTTP Server or HTTPS Server.

MorayM avatar Nov 03 '20 13:11 MorayM

This issue is kinda' obsolete since Yoga v3 is server agnostic, there is no generic way of extending the timeout - it needs to be done on the server itself.

Examples

Node

import { createSchema, createYoga } from 'graphql-yoga'
import { createServer } from 'node:http'

const yoga = createYoga({ ... })

const server = createServer(yoga)

server.setTimeout(5 * 60 * 1000) // 5 minute timeout

server.listen(4000, () => {
  console.info('Server is running on http://localhost:4000/graphql')
})

Express

import { createYoga } from 'graphql-yoga'
import express from 'express'

const app = express()

const yoga = createYoga({ ... })

app.use('/graphql', (req, res) => {
  res.setTimeout(5 * 60 * 1000) // 5 minute timeout
  yoga(req, res)
})

app.listen(4000, () => {
  console.info('Server is running on http://localhost:4000/graphql')
})

Fastify

import { createYoga } from 'graphql-yoga'
import fastify from 'fastify'

const app = fastify({
  requestTimeout: 5 * 60 * 1000, // 5 minute timeout
})

const yoga = createYoga({ ... })

app.route({
  url: '/graphql',
  method: ['GET', 'POST', 'OPTIONS'],
  handler: async (req, reply) => {
    const res = await yoga.handleNodeRequest(req, { req, reply })

    res.headers.forEach((value, key) => {
      reply.header(key, value)
    })

    reply.status(res.status)

    reply.send(res.body)

    return reply
  },
})

app.listen({ port: 4000 })

console.log(`Listening on http://localhost:4000/graphql`)

Koa

import { createYoga } from 'graphql-yoga'
import Koa from 'koa'

const app = new Koa()

const yoga = createYoga({ ... })

app.use(async (ctx) => {
  ctx.req.setTimeout(5 * 60 * 1000) // 5 minute timeout

  const res = await yoga.handleNodeRequest(ctx.req, ctx)

  ctx.status = res.status

  res.headers.forEach((value, key) => {
    ctx.append(key, value)
  })

  ctx.body = res.body
})

app.listen(4000, () => {
  console.log(`Listening on http://localhost:4000/graphql`)
})

enisdenjo avatar Sep 28 '22 09:09 enisdenjo

There appears to be undocumented behaviour with handleNodeRequest.

const response = await yoga.handleNodeRequest(request, {
  foo: request,
  request,
});

both inputs come out as different objects:

    context: async ({ request, foo }) => {
      console.log('>>>', foo === request);
>>> false

For whatever reason, the request object is being corrupted. It is supposed to have session property, but it is undefined. Meanwhile, foo.session works as expected.

punkpeye avatar Feb 24 '23 08:02 punkpeye