Skip to content

Commit

Permalink
Remove the use of enterWith
Browse files Browse the repository at this point in the history
Signed-off-by: Matteo Collina <[email protected]>
  • Loading branch information
mcollina committed May 21, 2024
1 parent dffba64 commit beb5ae2
Show file tree
Hide file tree
Showing 9 changed files with 56 additions and 289 deletions.
76 changes: 6 additions & 70 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,19 @@ npm i fastify fastify-asyncforge
## Usage

```js
// App.js
// app.mjs
import fastify from 'fastify'
import { start } from 'fastify-asyncforge'
import doWork from './do-work.mjs'
import asyncforge, { logger } from 'fastify-asyncforge'

const app = fastify({
logger: true
})
await app.register(asyncforge)

// It's fundamental that `start` is called before any other plugins are registered, otherwise the helpers
// would not work as expected
await start(app)
app.runInAsyncScope(() => {
logger().info('hello')
})

app.decorate('foo', 'bar')
app.decorateRequest('a')
Expand Down Expand Up @@ -54,71 +55,6 @@ export default function doWork () {
}
```

### enterWith

If you need to alter the current asynchronous context, you can use the `enterWith` helper.

```js
import { before, describe, it } from "node:test";
import Fastify from "fastify";
import asyncforge, { app, start } from "fastify-asyncforge";
import assert from "node:assert/strict";

let fastify;

async function build(config) {
const server = await Fastify();

server.register(asyncforge)
server.decorate("config", config);
console.log("config from memo", app().config);

return server;
}

describe("support exiting from a context", () => {
before(async () => {
fastify = await build({ foo: "bar" });
});

it("throws", () => {
assert.throws(app);
});

it("does not throw using enterWith", () => {
fastify.enterWith();
assert.equal(app(), fastify);
});
});
```

## Usage together with other async_hooks tools (e.g. DataDog, OpenTelemetry, etc)

If you are using `fastify-asyncforge` together with another `async_hooks` based tool,
you __must__ call `start` without adding an intermediate async function.
Alternatively, you'd need to use `.enterWith()`

```js
import fastify from 'fastify'
import asyncforge from 'fastify-asyncforge'

const fastify = Fastify()

async function wrap () {
// This is necessary to make it throw
await 1
await asyncforge.start(fastify)
}

await wrap()

// Calling .enterWith() is necessary or `asyncforge.app()` will throw
fastify.enterWith()
asyncforge.app()
```

If you are interested in knowing more, read https://github.com/nodejs/node/issues/53037.

## License

MIT
16 changes: 7 additions & 9 deletions example/app.js → example/app.mjs
Original file line number Diff line number Diff line change
@@ -1,17 +1,15 @@
'use strict'

const fastify = require('fastify')
const doWork = require('./do-work')
const { logger, start } = require('../index')
import fastify from 'fastify'
import doWork from './do-work.mjs'
import asyncforge, { logger } from '../index.js'

const app = fastify({
logger: true
})
app.register(require('../index'))

start(app)
await app.register(asyncforge)

logger().info('hello')
app.runInAsyncScope(() => {
logger().info('hello')
})

app.decorate('foo', 'bar')
app.decorateRequest('a')
Expand Down
6 changes: 2 additions & 4 deletions example/do-work.js → example/do-work.mjs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
'use strict'
import { logger, app, request, reply } from '../index.js'

const { logger, app, request, reply } = require('../')

module.exports = function doWork () {
export default function doWork () {
const log = logger()
log.info({
foo: app().foo,
Expand Down
2 changes: 1 addition & 1 deletion index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {

declare module "fastify" {
interface FastifyInstance {
enterWith: () => void;
runInAsyncScope<T> (fn: () => T) : T;
}
}

Expand Down
46 changes: 20 additions & 26 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,47 +1,41 @@
'use strict'

const fp = require('fastify-plugin')
const { memo, setAll } = require('asyncforge')
const { memo, create } = require('asyncforge')

const app = memo('fastify.app')
const request = memo('fastify.request')
const reply = memo('fastify.reply')
const logger = memo('fastify.logger')

const fastifyAsyncForge = fp(function (fastify, opts, next) {
fastify.decorate('enterWith', function () {
try {
app()
} catch {
setAll({
[app.key]: this,
[logger.key]: this.log
})
}
const store = create()

fastify.decorate('runInAsyncScope', function (fn) {
return store.run(fn)
})

fastify.addHook('onRequest', async function (req, res) {
setAll({
[app.key]: this,
[request.key]: req,
[reply.key]: res,
[logger.key]: req.log
fastify.addHook('onRequest', function (req, res, next) {
const store = create()

// We use callbacks because we cannot propagate through async/await
store.run(() => {
app.set(this)
request.set(req)
reply.set(res)
logger.set(req.log)
next()
})
})
next()
})

function start (fastify) {
setAll({
[app.key]: fastify,
[logger.key]: fastify.log
store.run(() => {
app.set(fastify)
logger.set(fastify.log)
next()
})

return fastify.register(fastifyAsyncForge)
}
})

module.exports = fastifyAsyncForge
module.exports.start = start
module.exports.app = app
module.exports.request = request
module.exports.reply = reply
Expand Down
3 changes: 1 addition & 2 deletions index.test-d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,11 @@ import fastify, {
const fastifyInstance = fastify();
expectAssignable<FastifyInstance>(fastifyInstance.register(fastifyasyncforge));
expectAssignable<FastifyPluginCallback>(fastifyasyncforge);
expectType<void>(fastifyInstance.enterWith());
expectType<number>(fastifyInstance.runInAsyncScope(() => 42));

// app
expectAssignable<FastifyInstance>(fastifyInstance);
expectAssignable<FastifyInstance>(app());
expectType<void>(app().enterWith());
expectAssignable<FastifyInstance>(app<FastifyInstance<RawServerDefault>>());
expectError<FastifyInstance>(app<string>());
expectError<FastifyInstance>({});
Expand Down
81 changes: 0 additions & 81 deletions test/async-hooks.test.js

This file was deleted.

61 changes: 19 additions & 42 deletions test/basic.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,12 @@ test('basic helpers with start', async (t) => {
const p = tspl(t, { plan: 7 })
const fastify = Fastify()

await fastifyAsyncForge.start(fastify)
await fastify.register(fastifyAsyncForge)

p.strictEqual(logger(), fastify.log)
p.strictEqual(app(), fastify)
fastify.runInAsyncScope(() => {
p.strictEqual(logger(), fastify.log)
p.strictEqual(app(), fastify)
})

fastify.get('/', async function (_request, _reply) {
p.strictEqual(app(), this)
Expand Down Expand Up @@ -61,43 +63,16 @@ test('basic helpers without start', async (t) => {
await p.completed
})

test('fastify.enterWith', async (t) => {
const p = tspl(t, { plan: 7 })
const fastify = Fastify()

await fastify.register(fastifyAsyncForge)

fastify.enterWith()

p.strictEqual(logger(), fastify.log)
p.strictEqual(app(), fastify)

fastify.get('/', async function (_request, _reply) {
p.strictEqual(app(), this)
p.strictEqual(request(), _request)
p.strictEqual(reply(), _reply)
p.strictEqual(logger(), _request.log)
return { hello: 'world' }
})

const res = await fastify.inject({
method: 'GET',
url: '/'
})

p.strictEqual(res.statusCode, 200)

await p.completed
})

test('with additional onRequest hook', async (t) => {

Check failure on line 66 in test/basic.test.js

View workflow job for this annotation

GitHub Actions / test (18.x)

with additional onRequest hook

Error [ERR_TEST_FAILURE]: create is not a function at process.emit (node:events:517:28) { failureType: 'uncaughtException', cause: TypeError [Error]: create is not a function at /home/runner/work/fastify-asyncforge/fastify-asyncforge/index.js:12:17 at Plugin.exec (/home/runner/work/fastify-asyncforge/fastify-asyncforge/node_modules/avvio/lib/plugin.js:125:28) at Boot._loadPlugin (/home/runner/work/fastify-asyncforge/fastify-asyncforge/node_modules/avvio/boot.js:432:10) at process.processTicksAndRejections (node:internal/process/task_queues:82:21), code: 'ERR_TEST_FAILURE' }

Check failure on line 66 in test/basic.test.js

View workflow job for this annotation

GitHub Actions / test (18.x)

with additional onRequest hook

Error [ERR_TEST_FAILURE]: create is not a function at process.emit (node:events:517:28) { failureType: 'uncaughtException', cause: TypeError [Error]: create is not a function at /home/runner/work/fastify-asyncforge/fastify-asyncforge/index.js:12:17 at Plugin.exec (/home/runner/work/fastify-asyncforge/fastify-asyncforge/node_modules/avvio/lib/plugin.js:125:28) at Boot._loadPlugin (/home/runner/work/fastify-asyncforge/fastify-asyncforge/node_modules/avvio/boot.js:432:10) at process.processTicksAndRejections (node:internal/process/task_queues:82:21), code: 'ERR_TEST_FAILURE' }

Check failure on line 66 in test/basic.test.js

View workflow job for this annotation

GitHub Actions / test (20.x)

with additional onRequest hook

Error [ERR_TEST_FAILURE]: create is not a function at process.emit (node:events:519:28) { code: 'ERR_TEST_FAILURE', failureType: 'uncaughtException', cause: TypeError [Error]: create is not a function at /home/runner/work/fastify-asyncforge/fastify-asyncforge/index.js:12:17 at Plugin.exec (/home/runner/work/fastify-asyncforge/fastify-asyncforge/node_modules/avvio/lib/plugin.js:125:28) at Boot._loadPlugin (/home/runner/work/fastify-asyncforge/fastify-asyncforge/node_modules/avvio/boot.js:432:10) at process.processTicksAndRejections (node:internal/process/task_queues:82:21) }

Check failure on line 66 in test/basic.test.js

View workflow job for this annotation

GitHub Actions / test (20.x)

with additional onRequest hook

Error [ERR_TEST_FAILURE]: create is not a function at process.emit (node:events:519:28) { code: 'ERR_TEST_FAILURE', failureType: 'uncaughtException', cause: TypeError [Error]: create is not a function at /home/runner/work/fastify-asyncforge/fastify-asyncforge/index.js:12:17 at Plugin.exec (/home/runner/work/fastify-asyncforge/fastify-asyncforge/node_modules/avvio/lib/plugin.js:125:28) at Boot._loadPlugin (/home/runner/work/fastify-asyncforge/fastify-asyncforge/node_modules/avvio/boot.js:432:10) at process.processTicksAndRejections (node:internal/process/task_queues:82:21) }

Check failure on line 66 in test/basic.test.js

View workflow job for this annotation

GitHub Actions / test (18.x)

with additional onRequest hook

Error [ERR_TEST_FAILURE]: create is not a function at process.emit (node:events:517:28) { failureType: 'uncaughtException', cause: TypeError [Error]: create is not a function at /home/runner/work/fastify-asyncforge/fastify-asyncforge/index.js:12:17 at Plugin.exec (/home/runner/work/fastify-asyncforge/fastify-asyncforge/node_modules/avvio/lib/plugin.js:125:28) at Boot._loadPlugin (/home/runner/work/fastify-asyncforge/fastify-asyncforge/node_modules/avvio/boot.js:432:10) at process.processTicksAndRejections (node:internal/process/task_queues:82:21), code: 'ERR_TEST_FAILURE' }

Check failure on line 66 in test/basic.test.js

View workflow job for this annotation

GitHub Actions / test (20.x)

with additional onRequest hook

Error [ERR_TEST_FAILURE]: create is not a function at process.emit (node:events:519:28) { code: 'ERR_TEST_FAILURE', failureType: 'uncaughtException', cause: TypeError [Error]: create is not a function at /home/runner/work/fastify-asyncforge/fastify-asyncforge/index.js:12:17 at Plugin.exec (/home/runner/work/fastify-asyncforge/fastify-asyncforge/node_modules/avvio/lib/plugin.js:125:28) at Boot._loadPlugin (/home/runner/work/fastify-asyncforge/fastify-asyncforge/node_modules/avvio/boot.js:432:10) at process.processTicksAndRejections (node:internal/process/task_queues:82:21) }
const p = tspl(t, { plan: 15 })
const fastify = Fastify()

await fastifyAsyncForge.start(fastify)
await fastify.register(fastifyAsyncForge)

p.strictEqual(logger(), fastify.log)
p.strictEqual(app(), fastify)
fastify.runInAsyncScope(() => {
p.strictEqual(logger(), fastify.log)
p.strictEqual(app(), fastify)
})

fastify.addHook('onRequest', async function b (_request, _reply) {
p.strictEqual(app(), this)
Expand Down Expand Up @@ -136,16 +111,18 @@ test('onRequest hook added before registration fails', async (t) => {
const fastify = Fastify()

fastify.addHook('onRequest', async function b (_request, _reply) {
p.strictEqual(app(), this)
p.strictEqual(logger(), fastify.log)
p.strictEqual(request(), undefined)
p.strictEqual(reply(), undefined)
p.throws(app)
p.throws(logger)
p.throws(request)
p.throws(reply)
})

await fastifyAsyncForge.start(fastify)
await fastify.register(fastifyAsyncForge)

p.strictEqual(logger(), fastify.log)
p.strictEqual(app(), fastify)
fastify.runInAsyncScope(() => {
p.strictEqual(logger(), fastify.log)
p.strictEqual(app(), fastify)
})

fastify.get('/', {
onRequest: async function a (_request, _reply) {
Expand Down
Loading

0 comments on commit beb5ae2

Please sign in to comment.