Repository navigation
Add /api/health endpoint with MongoDB/Redis dependency checks - #86
Conversation
Agent-Logs-Url: https://github.com/geturbackend/urBackend/sessions/de8db7a6-e16f-4427-8b4e-7737877312b3 Co-authored-by: Shivkumardhakad <202952715+Shivkumardhakad@users.noreply.github.com>
Agent-Logs-Url: https://github.com/geturbackend/urBackend/sessions/de8db7a6-e16f-4427-8b4e-7737877312b3 Co-authored-by: Shivkumardhakad <202952715+Shivkumardhakad@users.noreply.github.com>
/api/health endpoint with MongoDB/Redis dependency checks
There was a problem hiding this comment.
Pull request overview
Adds a new GET /api/health endpoint in apps/public-api to report API readiness by checking MongoDB and Redis connectivity and returning a structured JSON payload (200 when healthy, 503 when unhealthy).
Changes:
- Added
/api/healthrouter and mounted it in the public API app. - Implemented health controller logic for MongoDB (
mongoose.connection.readyState) and Redis (redis.status+ping()with timeout). - Added route-level Jest/Supertest coverage for healthy, Mongo disconnected, and Redis error scenarios.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| apps/public-api/src/routes/health.js | New router exposing GET / for the health endpoint. |
| apps/public-api/src/controllers/health.controller.js | Health evaluation logic for MongoDB + Redis with a ping timeout guard and structured response. |
| apps/public-api/src/app.js | Mounts the new health route under /api/health with existing middleware. |
| apps/public-api/src/tests/health.route.test.js | Adds tests validating status codes and dependency states. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| const pingResponse = await Promise.race([ | ||
| redis.ping(), | ||
| new Promise((resolve) => setTimeout(() => resolve('TIMEOUT'), REDIS_PING_TIMEOUT_MS)), | ||
| ]); | ||
| isRedisConnected = pingResponse === 'PONG'; |
There was a problem hiding this comment.
The Redis ping timeout is implemented with Promise.race + setTimeout, but the timeout timer is never cleared when redis.ping() resolves first. Under frequent health checks this leaves many unnecessary timers pending (and the ping promise can also continue running after the timeout wins), which can add avoidable event-loop overhead and resource usage. Consider creating an explicit timeout handle, unref() it, and clearTimeout() it in a finally block (and, if possible with the Redis client, use a cancellable/command-timeout mechanism instead of leaving in-flight pings running).
| test('returns error when redis is not responsive', async () => { | ||
| mockRedis.ping.mockRejectedValue(new Error('redis unavailable')); | ||
|
|
||
| const res = await request(app).get('/api/health'); | ||
|
|
||
| expect(res.status).toBe(503); | ||
| expect(res.body.status).toBe('error'); | ||
| expect(res.body.dependencies).toEqual({ | ||
| mongodb: 'connected', | ||
| redis: 'disconnected', | ||
| }); | ||
| }); | ||
| }); |
There was a problem hiding this comment.
The controller introduces a Redis ping timeout guard, but the tests only cover the case where ping() rejects. This doesn't verify the intended behavior when ping() hangs (the case the timeout is meant to protect against). Add a test where mockRedis.ping returns a never-resolving promise and assert the endpoint still responds (e.g., using Jest fake timers / advancing time) and marks Redis as disconnected.
|
@copilot apply changes based on the comments in this thread |
|
@coderabbitai ok to merge? |
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: Length of output: 6098
1. 🔴 Redis ping timeout — timer is never cleared (
|
| Check | Status |
|---|---|
| CI (lint, tests, CodeQL) | ✅ All passing |
| Branch state | ✅ Clean, no conflicts |
| Open review threads | ❌ 2 unresolved |
| Formal approval |
Recommendation: not yet ready to merge. Please address the two items above (or consciously decide to defer them) before proceeding.
|
@coderabbitai please create followup issue for this |
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: Length of output: 51
It tracks both deferred items:
Happy merging! 🐇 |
This PR introduces a dedicated
GET /api/healthendpoint for external monitoring to quickly assess API readiness and dependency connectivity. The endpoint reports health for MongoDB and Redis and returns a machine-readable status payload.Health endpoint
GET /api/healthroute inapps/public-api.limiter,logger) to match route protection patterns.Dependency status evaluation
mongoose.connection.readyState === 1redis.status === "ready"plusredis.ping()Response shape
status(ok/error)timestamp(ISO string)dependencies.mongodbanddependencies.redis(connected/disconnected)503when one or more dependencies are unhealthy.Focused coverage