-
-
Notifications
You must be signed in to change notification settings - Fork 2.3k
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
🚀 add 'onListen' application hook #4542
Comments
I just saw that we could do: import Fastify from 'fastify';
const PORT = parseInt(process.env.PORT, 10) || 4000;
const HOST = process.env.FASTIFY_LISTEN_HOST || 'localhost';
const fastify = Fastify();
fastify.server.on('listening', () => {
// /!\ some code that needs the server to accept requests
fastify.log.info('test');
});
fastify.listen({ port: PORT, host: HOST })
.then((address) => {
fastify.log.info(`Fastify server listening on http://localhost:${PORT} or ${address}`);
})
.catch((error) => {
fastify.log.error(error);
process.exit(1);
}); Feel free to close this issue if the new application hook is not usefull in that case. Edit: It seems that |
It's intended, the log line is executed a few microticks later. This would be a good addition. Would you like to send a PR? |
Sure, I will take a look. I have some "doubt" as the |
Hello @mcollina, I've done something locally, but clearly I'm not enough experienced with the JS Fastify base code and unit test standard. Should I still provide a PR without proper tests (as a draft or something like that) or would it be faster for you to implement it on your side? |
Hey! What are the doubts you have? I think you should start with the basics and provide some testing that verifies the new hook is triggered when it should, validations about the parameters for the hook, and so on. Open a PR (or a draft if you want to verify your test adds) and we can help you from there 🙂 |
@Yberion I have a concern about this idea. Here's what our tests for a plugin look like: const app = fastify();
beforeAll(async () => {
await app.register(PluginToBeTested);
await app.ready();
})
afterAll(async () => {
await app.close();
})
test('Case', () => {
const response = await app.inject({ url: '/', method: 'GET' });
//// ...
}) As you can see, we didn't start a real HTTP server here, which is a really cool feature of Fastify. I really love it. |
That's a pretty valid concern, though the new hook should not alter the current functionality of fastify. Meaning that as being a new implementation it should not have side effects on current features of the framework (e.g. testing). But the point is valid, how should the plugin behave while testing? We have either of two options:
I'm of course more into the first option, but just wanted to put all the cards over the table 🙂 |
Perhaps if @Yberion provides us with a real-world example of the |
Hello @metcoder95 & @erfanium, Sorry for the delay, I'm quite busy nowadays. This new hook should not block other hooks, it's just a short and more "Fastify" way of calling I'm using it on my project right now on our Angular SSR/SSG server, I request our CMS to retrieve all pages and after that generate the static pages by calling the fastify server and store them in a Redis cache server. // We can add logics once the server start accepting requests
fastify.server.on('listening', () => {
// Workaround in dev mode, the http proxy middleware from the Angular SSR dev server needs time to initialize.
// https://angular.io/api/core/isDevMode
if (isDevMode()) {
setTimeout(() => {
startCaching();
}, 2500); // Good computer
//}, 5000); // Bad computer
} else {
startCaching();
}
}); |
No problem at all! The use case is similar to do: await fastify.listen()
if (isDevMode()) {
setTimeout(() => {
startCaching();
}, 2500);
} else {
startCaching();
} I'm trying to imagine how |
I am thinking is import FastifyDelayRequest from 'fastify-delay-request'
import { once } from 'events'
// you can wrap it with encapsulation to prevent it
// from blocking the others API route
fastify.register(FastifyDelayRequest, {
})
fastify.delay.addTask(async function() {
// add task, like building cache here
// or, you can wait for listening event before others task
await once(fastify.server, 'listening')
}) In this case, your server is allowed to spin up and accepts requests while waiting for the caching jobs. |
Hello @Yberion @erfanium @metcoder95, |
👋 @yeeao The issue is still open and we welcome any contribution. Having a PR that proposes its design, is really welcome and can be a good starting point to gather ideas and adjust it accordingly 🙂 |
Thank you for the clarification and advice! |
Before we progress on the PR, we should discuss what we should do with errors. Should we throw and crash the fastify instance, or should we log errors and thats it. @Eomm wrote to me, that all other application hooks are necessary(!) to start for running the fastify instance, but onListen is not necessary anything. He thinks that logging by default makes most sense and if we want to crash the server because of an error, there should be an option or an errorHandler added to handle that.
@mcollina wrote to me that ".listen() should error, what ever this means". |
This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs. |
Prerequisites
🚀 Feature Proposal
We have an
onReady
hook used if we want to trigger things right before the server accept requests.We don't have a hook for when the server accept requests.
My proposal is to add a new application hook
onListen
for this purpose.I think it could act as the
onReady
application hook.Motivation
Currently if we want some code to be executed when the server accept requets we need to do something similar to this:
If we have a lot of code in this case or if we want to decouple the logic from inside this Promise, we currently cant.
I have a use case where I need to run the server which will request itself and cache the result of the request in a Redis server.
Also I'm not sure about that since I never used it, but it could also be usefull in serverless functions.
Example
We could even create plugins implementing logics with this new application hook (but I don't know how it would act as
listen()
is waiting for all plugins to be ready).The text was updated successfully, but these errors were encountered: