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

feat: Use new Node.js' connection closing API if available #3925

Merged
merged 1 commit into from
Jun 3, 2022
Merged

feat: Use new Node.js' connection closing API if available #3925

merged 1 commit into from
Jun 3, 2022

Conversation

ShogunPanda
Copy link
Contributor

@ShogunPanda ShogunPanda commented May 23, 2022

This PR aims to leverage the new Node.js 18.2.0 APIs if available and changes the forceCloseConnection option as follows:

  • forceCloseConnection=false - No connection handling is done
  • forceCloseConnection=true - Use closeAllConnections if available, otherwise the fastify connection handling.
  • forceCloseConnection="idle" - Use closeIdleConnections if available, otherwise throws an error.

The option defaults to "idle" if the server supports closeIdleConnections, otherwise to false.

Fixes #3924.

Copy link
Member

@mcollina mcollina left a comment

Choose a reason for hiding this comment

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

After seeing this... I would prefer a slightly different approach.

  1. Add a closeConnectionsOnClose option at the factory or to the close() method. Three options: false, 'idle', 'all'.
  2. The default value should 'idle' if it is available.
  3. throw if closeConnectionOnExit is set to a value that is not available on the current Node.js runtime.

The new behavior is applied automatically to fastify.close() and no new methods are added.

@ShogunPanda
Copy link
Contributor Author

Ok, makes sense. I'll rework it soon.

test/close.test.js Outdated Show resolved Hide resolved
@ShogunPanda
Copy link
Contributor Author

@mcollina As agreed, I've simplified this PR a lot.
No new API, the only two changes are the following:

  1. When available by the serverFactory (which, for the default Node.js HTTP server means 18.2.0), if forceCloseConnections is true, then server.closeIdleConnections is used.
  2. forceCloseConnections now defaults to true.

Hope this helps!

@mcollina
Copy link
Member

Can you update the PR title?

@mcollina mcollina requested a review from jsumners May 23, 2022 20:15
@@ -24,7 24,7 @@ module.exports.defaultInitOptions = ${JSON.stringify(defaultInitOptions)}
const defaultInitOptions = {
connectionTimeout: 0, // 0 sec
keepAliveTimeout: 72000, // 72 seconds
forceCloseConnections: false, // keep-alive connections
forceCloseConnections: true, // keep-alive connections
Copy link
Member

Choose a reason for hiding this comment

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

This is dangerous. There are ramifications that the user must know and account for. I disagree with enabling this by default.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I can easily revert this. But enabling this will IMHO make close behave a bit more like someone might expect.
Which ramification are you talking about? I can definitely update the docs if needed.

Copy link
Member

Choose a reason for hiding this comment

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

What ramifications? Those sockets are idle, there is no upstanding requests (minus the in-flight that we have not received yet).

On the other hand, making this the default improves the development experience and matches what people expects.

Copy link
Member

@climba03003 climba03003 May 24, 2022

Choose a reason for hiding this comment

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

I vote for not changing the default.
Add new option for closing behavior and default as idle, and when forceCloseConnections is true. It will be equal to all (which means call closeAllConnections).

Copy link
Member

Choose a reason for hiding this comment

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

Note that forceCloseConnections is not equal to all right now, only idle.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@mcollina Actually, after checking the source code, I realized that fastify behavior is more similar to http.Server.closeAllConnections.
Despite of the internal variable naming of keepAliveConnections, the .close will destroy ALL connected clients, not idle one only.
Shall I changed the method used?

Copy link
Member

@climba03003 climba03003 May 24, 2022

Choose a reason for hiding this comment

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

Yes, the current implementation is actually .closeAllConnections. It will destory all connections no matter the state.

The value from forceCloseConnections should be translated as follow to match the current behavior.

  1. true should translate to all
  2. false should translate to idle or false. I prefer idle here because it do not harms anyone if it close the idle connections.

Adding an extra option to explicitly disable the auto closing connections feature (in separate PR).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I just updated the PR. I think that false should disable connection closing at all. The next PR might instead add idle for the other behavior.

Reason is fastify is not capable at the moment of closing idle connections only.

Copy link
Contributor

Choose a reason for hiding this comment

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

If in this pr, forceCloseConnections is equal to all, I think it's better to use false by default

Copy link
Member

Choose a reason for hiding this comment

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

I agree.

fastify.js Outdated Show resolved Hide resolved
@ShogunPanda ShogunPanda changed the title feat: Added server.closeAllConnections and server.closeIdleConnections. feat: Use http.Server.closeIdleConnections if available May 24, 2022
@ShogunPanda
Copy link
Contributor Author

Can you update the PR title?

I've update it and the description as well.

fastify.js Outdated Show resolved Hide resolved
lib/route.js Outdated Show resolved Hide resolved
conn.destroy()
fastify[kKeepAliveConnections].delete(conn)
if (serverSupportsCloseAllConnections && options.forceCloseConnections) {
instance.server.closeAllConnections()
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
instance.server.closeAllConnections()
instance.server.closeIdleConnections()

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Well, here's the thing. If we just want to translate the existing behavior to the Node.js core provided one, then it's equivalent to closeAllConnections.

If instead we want to change the semantics, then yes, I will apply your suggestion.

Copy link
Member

Choose a reason for hiding this comment

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

ah gosh. Let's not flip the default and add an option to close only the idle connections.

lib/route.js Outdated Show resolved Hide resolved
@mcollina mcollina added this to the v4.0.0 milestone May 26, 2022
@mcollina
Copy link
Member

Can you rebase and regenerate the configValidator?

@ShogunPanda
Copy link
Contributor Author

@mcollina Done

@ShogunPanda ShogunPanda reopened this May 27, 2022
@ShogunPanda
Copy link
Contributor Author

(sorry, my finger slipped)

Copy link
Member

@mcollina mcollina left a comment

Choose a reason for hiding this comment

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

What I would like to achieve is that by default, if closeIdleConnections is available, it's used to shorten down the wait time.

@@ -24,7 24,7 @@ module.exports.defaultInitOptions = ${JSON.stringify(defaultInitOptions)}
const defaultInitOptions = {
connectionTimeout: 0, // 0 sec
keepAliveTimeout: 72000, // 72 seconds
forceCloseConnections: false, // keep-alive connections
forceCloseConnections: true, // keep-alive connections
Copy link
Member

Choose a reason for hiding this comment

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

I agree.

@ShogunPanda ShogunPanda changed the title feat: Use http.Server.closeIdleConnections if available feat: Use http.Server.closeIdleConnections and http.Server.closeAllConnections if available May 31, 2022
@ShogunPanda
Copy link
Contributor Author

I have updated the PR completely, see the new description above. How does it look now?

@mcollina I haven't changed the default as new APIs are not available in Node 16. We might flip this later once 18 reaches LTS.

docs/Reference/Server.md Outdated Show resolved Hide resolved
Copy link
Member

@mcollina mcollina left a comment

Choose a reason for hiding this comment

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

lgtm

lib/warnings.js Outdated Show resolved Hide resolved
fastify.js Outdated Show resolved Hide resolved
fastify.js Outdated Show resolved Hide resolved
test/close.test.js Outdated Show resolved Hide resolved
@ShogunPanda ShogunPanda changed the title feat: Use http.Server.closeIdleConnections and http.Server.closeAllConnections if available feat: Use new Node.js' connection closing API if available Jun 3, 2022
@ShogunPanda
Copy link
Contributor Author

I've force pushed the branch again. PTAL!

Copy link
Member

@mcollina mcollina left a comment

Choose a reason for hiding this comment

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

lgtm

@kibertoad kibertoad merged commit f3139a0 into fastify:main Jun 3, 2022
@ShogunPanda ShogunPanda deleted the close-all-connections branch June 4, 2022 06:35
@github-actions
Copy link

github-actions bot commented Jun 5, 2023

This pull request has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Jun 5, 2023
@jsumners jsumners added notable-change A change that should be explicitly outlined in release notes and migration guides and removed notable labels Oct 26, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
notable-change A change that should be explicitly outlined in release notes and migration guides
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Help on keep-alive connections
7 participants