Skip to content

Commit 3846068

Browse files
feat(api): add check on each database on healthcheck/db route
1 parent a367ebf commit 3846068

File tree

5 files changed

+54
-36
lines changed

5 files changed

+54
-36
lines changed

api/db/database-connection.js

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,16 @@ export class DatabaseConnection {
4242
configureConnectionExtension(this.knex);
4343
}
4444

45+
async checkStatus() {
46+
try {
47+
await this.knex.raw('SELECT 1');
48+
} catch (cause) {
49+
throw new Error(`Connection to database ${this.#name} not available.`, { cause });
50+
}
51+
}
52+
4553
async prepare() {
46-
await this.knex.raw('SELECT 1');
54+
await this.checkStatus();
4755
logger.info(`Connection to database ${this.#name} established.`);
4856
}
4957

api/db/database-connections.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ class DatabaseConnections {
1414
async disconnect() {
1515
return Promise.all(this.#connections.map((connection) => connection.disconnect()));
1616
}
17+
18+
async checkStatuses() {
19+
return Promise.all(this.#connections.map((connection) => connection.checkStatus()));
20+
}
1721
}
1822

1923
export const databaseConnections = new DatabaseConnections();

api/src/shared/application/healthcheck/healthcheck-controller.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import Boom from '@hapi/boom';
22

3-
import { knex } from '../../../../db/knex-database-connection.js';
3+
import { databaseConnections } from '../../../../db/database-connections.js';
44
import packageJSON from '../../../../package.json' with { type: 'json' };
55
import * as network from '../../../identity-access-management/infrastructure/utils/network.js';
66
import { config } from '../../config.js';
@@ -22,10 +22,10 @@ const get = function (request) {
2222

2323
const checkDbStatus = async function () {
2424
try {
25-
await knex.raw('SELECT 1 FROM knex_migrations_lock');
26-
return { message: 'Connection to database ok' };
27-
} catch {
28-
throw Boom.serverUnavailable('Connection to database failed');
25+
await databaseConnections.checkStatuses();
26+
return { message: 'Connection to databases ok' };
27+
} catch (error) {
28+
throw Boom.serverUnavailable(`Connection to databases failed: ${error.message}`);
2929
}
3030
};
3131

api/tests/shared/acceptance/application/healthcheck.route.test.js

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { databaseConnection } from '../../../../datamart/knex-database-connection.js';
12
import { createServer, expect } from '../../../test-helper.js';
23

34
describe('Acceptance | Shared | Application | Route | healthcheck', function () {
@@ -24,4 +25,39 @@ describe('Acceptance | Shared | Application | Route | healthcheck', function ()
2425
expect(response.result).to.equal('https://app.pix.org');
2526
});
2627
});
28+
29+
describe('GET /api/healthcheck/db', function () {
30+
it('returns an HTTP status code 200 when all databases are available', async function () {
31+
// given
32+
const options = {
33+
method: 'GET',
34+
url: '/api/healthcheck/db',
35+
};
36+
37+
// when
38+
const response = await server.inject(options);
39+
40+
// then
41+
expect(response.statusCode).to.equal(200);
42+
expect(response.result.message).to.equal('Connection to databases ok');
43+
});
44+
45+
it('returns an HTTP status code 503 when at least one database is not available', async function () {
46+
// given
47+
const options = {
48+
method: 'GET',
49+
url: '/api/healthcheck/db',
50+
};
51+
await databaseConnection.disconnect();
52+
53+
// when
54+
const response = await server.inject(options);
55+
56+
// then
57+
expect(response.statusCode).to.equal(503);
58+
expect(response.result.message).to.equal(
59+
'Connection to databases failed: Connection to database datamart not available.',
60+
);
61+
});
62+
});
2763
});

api/tests/shared/unit/application/healthcheck/healthcheck-controller_test.js

Lines changed: 0 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import { knex } from '../../../../../db/knex-database-connection.js';
21
import { healthcheckController } from '../../../../../src/shared/application/healthcheck/healthcheck-controller.js';
32
import { redisMonitor } from '../../../../../src/shared/infrastructure/utils/redis-monitor.js';
43
import { expect, hFake, sinon } from '../../../../test-helper.js';
@@ -22,35 +21,6 @@ describe('Unit | Controller | healthcheckController', function () {
2221
});
2322
});
2423

25-
describe('#checkDbStatus', function () {
26-
beforeEach(function () {
27-
sinon.stub(knex, 'raw');
28-
});
29-
30-
it('should check if DB connection is successful', async function () {
31-
// given
32-
knex.raw.resolves();
33-
34-
// when
35-
const response = await healthcheckController.checkDbStatus();
36-
37-
// then
38-
expect(response).to.include.keys('message');
39-
expect(response['message']).to.equal('Connection to database ok');
40-
});
41-
42-
it('should reply with a 503 error when the connection with the database is KO', function () {
43-
// given
44-
knex.raw.rejects();
45-
46-
// when
47-
const promise = healthcheckController.checkDbStatus(null, hFake);
48-
49-
// then
50-
expect(promise).to.be.rejectedWith(/Connection to database failed/);
51-
});
52-
});
53-
5424
describe('#checkRedisStatus', function () {
5525
beforeEach(function () {
5626
sinon.stub(redisMonitor, 'ping');

0 commit comments

Comments
 (0)