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

Unref the interval to allow server to exit #12

Open
wants to merge 4 commits into
base: master
Choose a base branch
from

Conversation

bttger
Copy link
Contributor

@bttger bttger commented Oct 10, 2022

If not unref'ed the event loop would always keep a single item in the loop and not exit

If not unref'ed the event loop would always keep a single item in the loop and not exit
Copy link
Member

@TimDaub TimDaub left a comment

Choose a reason for hiding this comment

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

thanks for your contribution. Please add a test

@bttger
Copy link
Contributor Author

bttger commented Oct 10, 2022

To be honest, I am not sure how to test this case. Locally, I test this via pressing Ctrl+C to exit the server. Do you have an idea?

@bttger
Copy link
Contributor Author

bttger commented Oct 10, 2022

I think, what we need to test is, if the interval still continues to work as expected (debugging this with a simple log output says yes), and the two cases that the server keeps running when unrefInterval = false and after the user interrupts it with a SIGINT/SIGTERM and vice versa.

@TimDaub
Copy link
Member

TimDaub commented Oct 10, 2022

To be honest, I am not sure how to test this case. Locally, I test this via pressing Ctrl+C to exit the server. Do you have an idea?

Can we read the items in the event loop? Because then we can just test if the conditions were met to see if unref was called or not

@bttger
Copy link
Contributor Author

bttger commented Oct 10, 2022

It seems like there is no simple way of checking what is left in the event queue. But I think it would be possible to observe all asynchronous calls and check for the Timeout type in the init and destroy async-hooks. I'll look into it when I have more time.

@TimDaub
Copy link
Member

TimDaub commented Oct 11, 2022

ok sounds good thank you!

@bttger
Copy link
Contributor Author

bttger commented Oct 12, 2022

I have added the tests with async_hooks.

@bttger bttger requested a review from TimDaub October 12, 2022 11:58
test/index_test.js Outdated Show resolved Hide resolved
@TimDaub
Copy link
Member

TimDaub commented Oct 13, 2022

I'm currently traveling until after Oct 18 and this is something I have to take a little while to understand so I hope you don't mind if this will take a week or two to get reviewed. Sorry!

@TimDaub
Copy link
Member

TimDaub commented Oct 19, 2022

I don't understand why we're trying to clear the interval with unref, I've not seen that anywhere. I'm only familiar with clearInterval and I've checked the nodejs docs and it seems to be the right usage: https://nodejs.org/docs/latest-v14.x/api/timers.html#timers_clearinterval_timeout

@@ -30,6 +30,8 @@ module.exports = ({ Store }) => {
intervalMs:
(options.expired && options.expired.intervalMs) ||
clearExpiredInterval,
unrefInterval: (options.expired && options.expired.unrefInterval) ||
Copy link
Member

Choose a reason for hiding this comment

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

we'd have to add any new option property to the documentation. And why do we need "|| false" ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, I will add it to the docs if you accept it to be added. Regarding the "false", that's redundant of course and I'll remove it.

@TimDaub
Copy link
Member

TimDaub commented Oct 19, 2022

If not unref'ed the event loop would always keep a single item in the loop and not exit

I'm not sure I understand the use case. In an application like a webserver, I can't think of a moment when the interval should truly be cleared. E.g. a webserver runs indefinitely and so the interval should technically only be cleared when the server shuts down, in which case that takes care of itself, or not?

@bttger
Copy link
Contributor Author

bttger commented Oct 19, 2022

I don't understand why we're trying to clear the interval with unref, I've not seen that anywhere. I'm only familiar with clearInterval and I've checked the nodejs docs and it seems to be the right usage: https://nodejs.org/docs/latest-v14.x/api/timers.html#timers_clearinterval_timeout

No I don't want to clear the interval because then it wouldn't remove stale sessions anymore. I only want to ensure that the server can gracefully terminate. E.g. when I start a fastify server and then press Ctrl+C, it stops the server but the background interval to clean the sessions keeps it from terminating the process. The following snippet shows a common way to implement graceful shutdowns:

const SHUTDOWN_TIMEOUT = 10 * 1000; // default 10 secs
const signals = ["SIGINT", "SIGTERM"];
signals.forEach((signal) => {
  process.once(signal, () => {
    // Make sure server terminates after timeout
    setTimeout(() => {
      process.exit(1);
    }, SHUTDOWN_TIMEOUT).unref();

    // Do stuff to clean up
    server.close();
  });
});

Here we also unref the timeout that ensures that it will definitely terminate. If the event loop empties first, then the server can terminate before.

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.

2 participants