Graceful shutdown only works if fastify server started and terminates without processing any requests
ctv-bigi opened this issue · comments
When testing this plugin, I find that it only works (fastify v4) when I start the server, then ctrl-c immediately to shut it down. It gracefully shuts down correctly and runs any onClose
hooks I have.
If I start the server, make a request hit to a route handler, and then ctrl-c to shut it down, it gets stuck and always waits for the 10s timeout.
This happens even if that route handler does nothing at all.
Hi @ctv-bigi thank you for reporting the issue. I was able to reproduce it. You can fix it by listening on ipv4 address 127.0.0.1
instead of localhost
which listen to dual stack on most systems.
@StarpTech Hi, i has the same probrem
server.register(require('fastify-graceful-shutdown'))
.after(() => {
server.gracefulShutdown(async (signal, next) => {
console.log(`Upps! ${signal}`)
await server.close()
console.log(`server closed`)
next()
})
})
server.route({
url: "/",
method: "GET",
handler: async function (request, reply) {
console.log('start wait timeout');
await new Promise<void>((RES) => {
setTimeout(() => {
RES()
}, 5000);
})
console.log('5s end');
return {
status: "up",
};
},
});
server.listen(
{
host: "0.0.0.0",
port: 3000,
},
(err) => {
if (err) {
console.error(err);
process.exit(1);
}
}
);
I run node app.js and ctrl+c
shutdown, the log like this.
0s start wait timeout
3s Upps! SIGINT
5s end
10s [2024-03-23 21:04:53.661 +0800] ERROR: terminate process after timeout {"plugin":"fastify-graceful-shutdown","signal":"SIGINT","timeout":10000}
Why not stop immediately after the route return of 5s
?
Hi, I can't reproduce it. You should not close the server yourself. The plugin will call it after all other handlers has been called.
'use strict'
const fastify = require('fastify')({
logger: {
level: 'info',
},
})
fastify.register(require('./')).after((err) => {
fastify.log.error(err)
// Register custom clean up handler
fastify.gracefulShutdown((code, cb) => {
fastify.log.info('Graceful shutdown ...')
cb()
fastify.log.info('Graceful shutdown complete')
})
})
const schema = {
schema: {
response: {
200: {
type: 'object',
properties: {
hello: {
type: 'string',
},
},
},
},
},
}
fastify.get('/', schema, async function (req, reply) {
await new Promise((resolve, reject) => {
setTimeout(() => {
resolve()
}, 5000)
})
reply.send({ hello: 'world' })
})
fastify.listen(
{
host: '127.0.0.1',
port: 3000,
},
(err) => {
if (err) throw err
console.log(`server listening on ${fastify.server.address().port}`)
},
)
{"level":50,"time":1711214092034,"pid":248845,"hostname":"pop-os","msg":null}
server listening on 3000
{"level":30,"time":1711214092040,"pid":248845,"hostname":"pop-os","msg":"Server listening at http://127.0.0.1:3000"}
{"level":30,"time":1711214099827,"pid":248845,"hostname":"pop-os","reqId":"req-1","req":{"method":"GET","url":"/","hostname":"localhost:3000","remoteAddress":"127.0.0.1","remotePort":53902},"msg":"incoming request"}
^C{"level":30,"time":1711214101301,"pid":248845,"hostname":"pop-os","msg":"Graceful shutdown ..."}
{"level":30,"time":1711214101301,"pid":248845,"hostname":"pop-os","msg":"Graceful shutdown complete"}
{"level":30,"time":1711214104831,"pid":248845,"hostname":"pop-os","reqId":"req-1","res":{"statusCode":200},"responseTime":5003.497728999704,"msg":"request completed"}
{"level":30,"time":1711214104894,"pid":248845,"hostname":"pop-os","reqId":"req-2","res":{"statusCode":503},"msg":"request aborted - refusing to accept new requests as server is closing"}
@StarpTech Hi, please try this
'use strict'
const fastify = require('fastify')({
logger: {
level: 'info',
},
})
fastify.register(require('fastify-graceful-shutdown')).after((err) => {
fastify.log.error(err)
// Register custom clean up handler
fastify.gracefulShutdown((code, cb) => {
fastify.log.info('Graceful shutdown ...')
cb()
fastify.log.info('Graceful shutdown complete')
})
})
fastify.get('/', async function (req, reply) {
console.log('start');
await new Promise((resolve, reject) => {
setTimeout(() => {
resolve()
}, 5000)
})
console.log('end');
reply.send({ hello: 'world' })
})
fastify.listen(
{
host: '127.0.0.1',
port: 3000,
}
)
shell
$ node app.js
{"level":50,"time":1711259359199,"pid":100903,"hostname":"ubuntu-server","msg":null}
{"level":30,"time":1711259359201,"pid":100903,"hostname":"ubuntu-server","msg":"Server listening at http://127.0.0.1:3000"}
{"level":30,"time":1711259361030,"pid":100903,"hostname":"ubuntu-server","reqId":"req-1","req":{"method":"GET","url":"/?vscodeBrowserReqId=1711259360797","hostname":"localhost:3000","remoteAddress":"127.0.0.1","remotePort":36048},"msg":"incoming request"}
start
^C{"level":30,"time":1711259362266,"pid":100903,"hostname":"ubuntu-server","msg":"Graceful shutdown ..."}
{"level":30,"time":1711259362266,"pid":100903,"hostname":"ubuntu-server","msg":"Graceful shutdown complete"}
end
{"level":30,"time":1711259366037,"pid":100903,"hostname":"ubuntu-server","reqId":"req-1","res":{"statusCode":200},"responseTime":5006.029588997364,"msg":"request completed"}
{"level":50,"time":1711259372270,"pid":100903,"hostname":"ubuntu-server","plugin":"fastify-graceful-shutdown","signal":"SIGINT","timeout":10000,"msg":"terminate process after timeout"}
What Node.js, Fastify versioning are you using?
What Node.js, Fastify versioning are you using?
- node: v21.7.1
- fastify: 4.26.2
I use Node 20. What is your operating system? Those are my logs from your example after a single request.
{"level":50,"time":1711276410599,"pid":19248,"hostname":"pop-os","msg":null}
{"level":30,"time":1711276410601,"pid":19248,"hostname":"pop-os","msg":"Server listening at http://127.0.0.1:3000"}
{"level":30,"time":1711276415582,"pid":19248,"hostname":"pop-os","reqId":"req-1","req":{"method":"GET","url":"/","hostname":"localhost:3000","remoteAddress":"127.0.0.1","remotePort":49580},"msg":"incoming request"}
start
^C{"level":30,"time":1711276417053,"pid":19248,"hostname":"pop-os","msg":"Graceful shutdown ..."}
{"level":30,"time":1711276417053,"pid":19248,"hostname":"pop-os","msg":"Graceful shutdown complete"}
end
{"level":30,"time":1711276420586,"pid":19248,"hostname":"pop-os","reqId":"req-1","res":{"statusCode":200},"responseTime":5004.05306299997,"msg":"request completed"}
{"level":30,"time":1711276420648,"pid":19248,"hostname":"pop-os","reqId":"req-2","res":{"statusCode":503},"msg":"request aborted - refusing to accept new requests as server is closing"}
I use ubuntu22.04, thanks you, i may know the problem
It can be work use curl
- node app.js
- curl http://127.0.0.1:3000
- ctrl+c
- it wait the response return and exit service
And use chrome, it terminate process after timeout...
- node app.js
- chrome input http://127.0.0.1:3000
- ctrl+c
- it wait the response return and terminate process after timeout