Skip to content

Commit

Permalink
feat(healthcheck): expose state to health checks (#185)
Browse files Browse the repository at this point in the history
  • Loading branch information
okv committed May 21, 2021
1 parent 5a442df commit ba3f67f
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 4 deletions.
5 changes: 3 additions & 2 deletions README.md
Expand Up @@ -30,7 +30,8 @@ function onShutdown () {
console.log('cleanup finished, server is shutting down');
}

function healthCheck () {
function healthCheck ({ state }) {
// `state.isShuttingDown` (boolean) shows whether the server is shutting down or not
return Promise.resolve(
// optionally include a resolve value to be included as
// info in the health check response
Expand All @@ -50,7 +51,7 @@ const server = http.createServer((request, response) => {
const options = {
// health check options
healthChecks: {
'/healthcheck': healthCheck, // a function returning a promise indicating service health,
'/healthcheck': healthCheck, // a function accepting a state and returning a promise indicating service health,
verbatim: true, // [optional = false] use object returned from /healthcheck verbatim in response,
__unsafeExposeStackTraces: true // [optional = false] return stack traces in error response if healthchecks throw errors
},
Expand Down
2 changes: 1 addition & 1 deletion lib/standalone-tests/terminus.onsignal.nofail.js
Expand Up @@ -7,7 +7,7 @@ const SIGNAL = 'SIGINT'

createTerminus(server, {
healthChecks: {
'/health': () => Promise.resolve()
'/health': ({ state }) => Promise.resolve({ state })
},
sendFailuresDuringShutdown: false,
signal: SIGNAL,
Expand Down
2 changes: 1 addition & 1 deletion lib/terminus.js
Expand Up @@ -85,7 +85,7 @@ function decorateWithHealthCheck (server, state, options) {
}
let info
try {
info = await healthCheck()
info = await healthCheck({ state })
} catch (error) {
logger('healthcheck failed', error)
return sendFailure(res, { error: error.causes, exposeStackTraces: healthChecks.__unsafeExposeStackTraces })
Expand Down
48 changes: 48 additions & 0 deletions lib/terminus.spec.js
Expand Up @@ -216,6 +216,54 @@ describe('Terminus', () => {
expect(loggerRan).to.eql(true)
})

it('exposes internal state (isShuttingDown: false) to health check', async () => {
let onHealthCheckRan = false
let exposedState

createTerminus(server, {
healthChecks: {
'/health': ({ state }) => {
onHealthCheckRan = true
exposedState = state
return Promise.resolve()
}
}
})
server.listen(8000)

const response = await fetch('http://localhost:8000/health')
expect(response.status).to.eql(200)
expect(response.headers.has('Content-Type')).to.eql(true)
expect(response.headers.get('Content-Type')).to.eql('application/json')
expect(onHealthCheckRan).to.eql(true)
expect(exposedState).to.eql({ isShuttingDown: false })
})

it('exposes internal state (isShuttingDown: true) when shutting down', (done) => {
let responseAssertionsComplete = false
let exposedState

// We're only truly finished when the response has been analyzed and the forked http process has exited,
// freeing up port 8000 for future tests
execFile('node', ['lib/standalone-tests/terminus.onsignal.nofail.js'], (error) => {
expect(error.signal).to.eql('SIGINT')
expect(responseAssertionsComplete).to.eql(true)
expect(exposedState).to.eql({ isShuttingDown: true })
done()
})

// let the process start up
setTimeout(() => {
fetch('http://localhost:8000/health')
.then(async (res) => {
expect(res.status).to.eql(200)
responseAssertionsComplete = true
const json = await res.json()
exposedState = json.info.state
})
}, 300)
})

describe('includes error on reject', async () => {
const errors = [
new Error('test error 1'),
Expand Down

0 comments on commit ba3f67f

Please sign in to comment.