Skip to content

Commit 888e917

Browse files
Merge pull request #315 from blockfrost/fix/health-timeout-log
fix: timeout log even when dbsync conn succeeded
2 parents 9de0963 + 54ec922 commit 888e917

File tree

4 files changed

+56
-20
lines changed

4 files changed

+56
-20
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
## [6.3.3] - 2026-03-13
11+
12+
### Fixed
13+
14+
- Fixed `/health` timeout race condition where the timeout log would fire even when the DB connection succeeded in time
15+
1016
## [6.3.2] - 2026-03-11
1117

1218
### Changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "blockfrost-backend-ryo",
3-
"version": "6.3.2",
3+
"version": "6.3.3",
44
"description": "",
55
"keywords": [],
66
"license": "Apache-2.0",

src/routes/health/index.ts

Lines changed: 24 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -18,25 +18,30 @@ async function route(fastify: FastifyInstance) {
1818
let dbHealthy = true;
1919

2020
if (healthCheckDbTimeoutMs !== undefined) {
21-
const connected = await Promise.race([
22-
getDbSync(fastify)
23-
.then(client => {
24-
client.release();
25-
return true;
26-
})
27-
.catch((error: unknown) => {
28-
console.error(`[HEALTH]: unhealthy — DB connection error`, error);
29-
return false;
30-
}),
31-
new Promise<boolean>(resolve =>
32-
setTimeout(() => {
33-
console.error(
34-
`[HEALTH]: unhealthy — DB connection timed out after ${healthCheckDbTimeoutMs}ms`,
35-
);
36-
resolve(false);
37-
}, healthCheckDbTimeoutMs),
38-
),
39-
]);
21+
let timer: ReturnType<typeof setTimeout> | undefined;
22+
23+
const dbPromise = getDbSync(fastify)
24+
.then(client => {
25+
clearTimeout(timer);
26+
client.release();
27+
return true;
28+
})
29+
.catch((error: unknown) => {
30+
clearTimeout(timer);
31+
console.error(`[HEALTH]: unhealthy — DBSync connection error`, error);
32+
return false;
33+
});
34+
35+
const timeoutPromise = new Promise<boolean>(resolve => {
36+
timer = setTimeout(() => {
37+
console.error(
38+
`[HEALTH]: unhealthy — DBSync did not respond within ${healthCheckDbTimeoutMs}ms`,
39+
);
40+
resolve(false);
41+
}, healthCheckDbTimeoutMs);
42+
});
43+
44+
const connected = await Promise.race([dbPromise, timeoutPromise]);
4045

4146
if (!connected) {
4247
dbHealthy = false;

test/unit/tests/routes/health.unit.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,4 +66,29 @@ describe('health endpoints tests', () => {
6666

6767
fastify.close();
6868
});
69+
70+
test('does not log timeout error when DB responds before healthCheckDbTimeoutMs', async () => {
71+
// Use a short timeout so we can wait past it and verify the log never fires
72+
mainConfig.server.healthCheckDbTimeoutMs = 50;
73+
74+
const fastify = buildFastify();
75+
const errorSpy = vi.spyOn(console, 'error');
76+
77+
vi.spyOn(databaseUtils, 'getDbSync').mockReturnValue(
78+
// @ts-expect-error test
79+
Promise.resolve({ release: () => null }),
80+
);
81+
82+
await fastify.ready();
83+
const response = await supertest(fastify.server).get('/health');
84+
85+
expect(response.body).toEqual({ is_healthy: true });
86+
87+
// Wait past the timeout to ensure the timer was actually cancelled
88+
await new Promise(resolve => setTimeout(resolve, 100));
89+
90+
expect(errorSpy).not.toHaveBeenCalledWith(expect.stringContaining('did not respond within'));
91+
92+
fastify.close();
93+
});
6994
});

0 commit comments

Comments
 (0)