Skip to content

Commit

Permalink
Improve error handling and observability
Browse files Browse the repository at this point in the history
  • Loading branch information
Igor Savin committed Nov 20, 2024
1 parent eb39da3 commit 9dba1c7
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 46 deletions.
16 changes: 14 additions & 2 deletions lib/fastifyAwilixPlugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,20 @@ function plugin (fastify, opts, next) {
})

if (opts.asyncInit || opts.eagerInject) {
fastify.addHook('onReady', (done) => {
awilixManager.executeInit().then(done, done)
fastify.addHook('onReady', function awilixOnReady (done) {
const startTime = Date.now()
fastify.log.debug('Start async awilix init')
awilixManager.executeInit().then(() => {
const endTime = Date.now()
fastify.log.debug(`Finished async awilix init in ${endTime - startTime} msecs`)
done()
}, (err) => {
if (err) {
fastify.log.error('Error during async awilix init')
done(err)
}
done()
})
})
}

Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@
"@types/node": "^22.0.0",
"awilix": "^12.0.1",
"c8": "^10.1.2",
"fastify": "^5.0.0",
"fastify": "^5.1.0",
"pino": "^9.5.0",
"snazzy": "^9.0.0",
"standard": "^17.1.0",
"tsd": "^0.31.0"
Expand Down
114 changes: 71 additions & 43 deletions test/fastifyAwilixPlugin.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ const { describe, it, afterEach } = require('node:test')
const assert = require('node:assert')

const { diContainer, diContainerClassic, fastifyAwilixPlugin } = require('../lib')
const pino = require('pino')

class UserServiceClassic {
constructor (userRepository, maxUserName, maxEmail) {
Expand Down Expand Up @@ -69,61 +70,63 @@ describe('fastifyAwilixPlugin', () => {
return app.close()
})

variations.forEach((variation) => {
describe(variation.injectionMode, () => {
describe('inject singleton', () => {
it('injects correctly', async () => {
class UserRepository {
constructor () {
this.id = 'userRepository'
describe('variations', () => {
variations.forEach((variation) => {
describe(variation.injectionMode, () => {
describe('inject singleton', () => {
it('injects correctly', async () => {
class UserRepository {
constructor () {
this.id = 'userRepository'
}
}
}

const maxUserNameVariableFactory = () => {
return 10
}
const maxUserNameVariableFactory = () => {
return 10
}

const maxUserPasswordVariableFactory = async () => {
return await Promise.resolve(20).then((result) => result)
}
const maxUserPasswordVariableFactory = async () => {
return await Promise.resolve(20).then((result) => result)
}

app = fastify({ logger: true })
const endpoint = async (req, res) => {
const userService = app.diContainer.resolve('userService')
app = fastify({ logger: true })
const endpoint = async (req, res) => {
const userService = app.diContainer.resolve('userService')

assert.equal(userService.userRepository.id, 'userRepository')
assert.equal(userService.maxUserName, 10)
assert.equal(userService.maxEmail, 40)
assert.equal(userService.userRepository.id, 'userRepository')
assert.equal(userService.maxUserName, 10)
assert.equal(userService.maxEmail, 40)

const maxUserPassword = await req.diScope.resolve('maxUserPassword')
const maxUserPassword = await req.diScope.resolve('maxUserPassword')

assert.equal(maxUserPassword, 20)
assert.equal(maxUserPassword, 20)

res.send({
status: 'OK'
})
}
res.send({
status: 'OK'
})
}

app.register(fastifyAwilixPlugin, {
injectionMode: variation.optsInjectionMode,
container: variation.optsContainer
})
variation.container.register({
userService: asClass(variation.UserService),
userRepository: asClass(UserRepository, { lifetime: Lifetime.SINGLETON }),
maxUserName: asFunction(maxUserNameVariableFactory, { lifetime: Lifetime.SINGLETON }),
maxUserPassword: asFunction(maxUserPasswordVariableFactory, {
lifetime: Lifetime.SINGLETON
}),
maxEmail: asValue(40)
})
app.register(fastifyAwilixPlugin, {
injectionMode: variation.optsInjectionMode,
container: variation.optsContainer
})
variation.container.register({
userService: asClass(variation.UserService),
userRepository: asClass(UserRepository, { lifetime: Lifetime.SINGLETON }),
maxUserName: asFunction(maxUserNameVariableFactory, { lifetime: Lifetime.SINGLETON }),
maxUserPassword: asFunction(maxUserPasswordVariableFactory, {
lifetime: Lifetime.SINGLETON
}),
maxEmail: asValue(40)
})

app.post('/', endpoint)
await app.ready()
app.post('/', endpoint)
await app.ready()

const response = await app.inject().post('/').end()
const response = await app.inject().post('/').end()

assert.equal(response.statusCode, 200)
assert.equal(response.statusCode, 200)
})
})
})
})
Expand All @@ -141,4 +144,29 @@ describe('fastifyAwilixPlugin', () => {
}, /If you are passing pre-created container explicitly, you cannot specify injection mode/)
})
})

describe('plugin', () => {
it('handles DI timeout', async () => {
app = fastify({
loggerInstance: pino({
level: 'debug'
})
})
app.register(fastifyAwilixPlugin, {
container: diContainer,
asyncInit: true
})
diContainer.register('throwAnError', asFunction(() => {
return {
asyncInit: async () => {
throw new Error('failed to init')
}
}
}, {
asyncInit: 'asyncInit',
eagerInject: true
}))
await assert.rejects(app.ready(), /failed to init/)
})
})
})

0 comments on commit 9dba1c7

Please sign in to comment.