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

Create a separate hook runner for onSend hooks #795

Merged
merged 2 commits into from Feb 19, 2018

Conversation

nwoltman
Copy link
Contributor

The onSend hooks are a special case because they need extra logic for changing the payload. This extra logic is not needed for the other hooks and it makes the other hooks prone to a bug where the hook runner's internal state will be changed if a hook function returns a promise that resolves to a value other than undefined.

Example of the bug that this change prevents
const fastify = require('./')()

fastify.addHook('preHandler', (request, reply) => {
  return Promise.resolve() // OK
})

fastify.addHook('preHandler', (request, reply) => {
  return Promise.resolve(true) // Causes crash
})

fastify.get('/', (request, reply) => {
  reply.send('hello')
})

fastify.inject('/', (err, res) => {
  console.log('Will not reach here')
})
(node:12944) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'finished' of undefined
    at preHandlerCallback (~/fastify/lib/handleRequest.js:80:17)
    at next (~/fastify/lib/hookRunner.js:17:7)
    at handleResolve (~/fastify/lib/hookRunner.js:28:5)
    at <anonymous>
    at process._tickCallback (internal/process/next_tick.js:160:7)
    at Function.Module.runMain (module.js:703:11)
    at startup (bootstrap_node.js:190:16)
    at bootstrap_node.js:662:3

This change adds a second hook runner just for onSend hooks that helps make the code that starts the hooks cleaner (it's no longer necessary to call .bind(reply) during a request) and the main hook runner is simplified so that changing its internal state is no longer possible.

This also improves the hooks benchmark by 450-600 req/sec.

Benchmark

Before

[1] Stat         Avg     Stdev   Max
[1] Latency (ms) 2.58    6.92    195.71
[1] Req/Sec      35211.2 6839.11 39080
[1] Bytes/Sec    5.26 MB 1.03 MB 5.82 MB
[1]
[1] 176k requests in 5s, 26.2 MB read
...
[1] Stat         Avg     Stdev   Max
[1] Latency (ms) 2.61    6.8     165.82
[1] Req/Sec      34753.6 7256.24 39432
[1] Bytes/Sec    5.23 MB 1.08 MB 5.88 MB
[1]
[1] 174k requests in 5s, 25.9 MB read

After

[1] Stat         Avg      Stdev   Max
[1] Latency (ms) 2.57     7.03    198.39
[1] Req/Sec      35204.81 7148.29 40124
[1] Bytes/Sec    5.23 MB  1.08 MB 5.98 MB
[1]
[1] 176k requests in 5s, 26.2 MB read
...
[1] Stat         Avg      Stdev   Max
[1] Latency (ms) 2.53     6.8     190.88
[1] Req/Sec      35812.81 6979.73 39894
[1] Bytes/Sec    5.31 MB  1.05 MB 5.94 MB
[1]
[1] 179k requests in 5s, 26.7 MB read

Checklist

  • run npm run test and npm run benchmark
  • tests and/or benchmarks are included
  • documentation is changed or added
  • commit message and code follows Code of conduct

The `onSend` hooks are a special case because they need extra logic for changing the payload. This extra logic is not needed for the other hooks and it makes the other hooks more prone to a bug where the hook runner's internal state will be changed if a hook function returns a promise that resolves to a value that is not `undefined`.

This change adds a second hook runner just for `onSend` hooks that helps simplify the logic for calling the runner (it's no longer necessary to call `.bind(reply)` during a request) and the main hook runner is simplified so that changing its internal state is no longer possible.

This also improves the hooks benchmarks by 450-600 req/sec.
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.

Can you please add a test for the original bug you wanted to solve?

@nwoltman
Copy link
Contributor Author

@mcollina
Copy link
Member

mcollina commented Feb 18, 2018 via email

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

@delvedor delvedor added the bugfix Issue or PR that should land as semver patch label Feb 19, 2018
Copy link
Member

@delvedor delvedor left a comment

Choose a reason for hiding this comment

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

LGTM

@delvedor delvedor merged commit 86519c8 into fastify:master Feb 19, 2018
@github-actions
Copy link

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 Feb 19, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bugfix Issue or PR that should land as semver patch
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants