Skip to content

Feature/db health check - #153

Open
Keengfk wants to merge 3 commits into
stellar-vortex-protocol:mainfrom
Keengfk:feature/db-health-check
Open

Feature/db health check#153
Keengfk wants to merge 3 commits into
stellar-vortex-protocol:mainfrom
Keengfk:feature/db-health-check

Conversation

@Keengfk

@Keengfk Keengfk commented Jul 27, 2026

Copy link
Copy Markdown

Summary

/health previously only reflected process liveness. Once the app has a real
PostgreSQL dependency (issue #36), a healthy process with an unreachable
database would still return status: "ok" — misleading for operators and
alerting systems. This PR adds a db field to the health response that reports
connectivity independently of process health, with graceful degradation so the
endpoint always responds even when the database is down.

───────────────────────────────────────────────────────────────────────────────

Changes

src/health/database-health.service.ts (new)
Probes the database using PrismaService.$queryRaw\SELECT 1`` — this exercises
the real connection pool rather than a separate client. The query races against
a 3-second timeout. The method never throws; callers always receive a typed
result:

{ status: "ok", latencyMs: number } // database answered in time
{ status: "unreachable", error: string } // query failed or timed out

src/health/health.controller.ts (modified)
check() is now async and includes the db result in every response:

{
"status": "ok",
"service": "vortex-backend",
"version": "0.1.0",
"network": "stellar-testnet",
"uptime": 42.3,
"db": { "status": "ok", "latencyMs": 2 }
}

When the database is unreachable:

{
"db": { "status": "unreachable", "error": "Can't reach database server at
localhost:5432" }
}

src/health/health.module.ts (modified)
Provides DatabaseHealthService. PrismaModule is already @global() so no
additional import is needed.

───────────────────────────────────────────────────────────────────────────────

Design decisions

  • Never returns a non-200 status — the process itself is healthy even if the DB
    is down. Consumers (load balancers, uptime monitors) that key off HTTP status
    are unaffected; richer monitors can inspect the db.status field.
  • Timeout is fixed at 3s — long enough to avoid false positives on slow
    connections, short enough to keep the health endpoint responsive. Can be made
    configurable via AppConfig in a follow-up.
  • Uses the existing Prisma connection pool — no second connection string, no
    separate pg client. Pool config comes from DATABASE_URL in AppConfig/env,
    consistent with the pattern used by stellar.sorobanRpcUrl.

───────────────────────────────────────────────────────────────────────────────

Testing

src/health/database-health.service.spec.ts (new) — 4 unit tests with a mocked
PrismaService:

  • Query succeeds → status: "ok", latencyMs is a non-negative number
  • Query rejects → status: "unreachable", error message captured
  • Query hangs past timeout (fake timers) → status: "unreachable", error matches
    /timed out/i
  • $queryRaw missing entirely → never throws, returns status: "unreachable"

test/health.e2e-spec.ts (updated) — asserts the db field is always present and
structurally valid for both the ok and unreachable branches. The e2e suite runs
with the mock PrismaService (no real DB), which exercises the
graceful-degradation path.

npm run lint ✓ 0 errors
npm run typecheck ✓ 0 errors
npm run build ✓ clean
npm test ✓ 39 tests, 6 suites (+4 new)
npm run test:e2e ✓ 23 tests, 5 suites

closes #58

Keengfk added 3 commits July 27, 2026 20:12
- Add Prisma 5.22.0 (prisma + @prisma/client) as dependencies
- Add prisma/schema.prisma with Intent, Solver, Token models and
  IntentState / SupportedChain enums; all fields indexed appropriately
- Add initial migration SQL (prisma/migrations/20240101000000_init/)
- Add PrismaService (extends PrismaClient, NestJS lifecycle hooks) and
  global PrismaModule; wire into AppModule
- Add DATABASE_URL to Joi validation schema, AppConfig, and .env.example
- Add npm scripts: db:generate, db:migrate, db:migrate:prod, db:studio,
  db:validate
- Update Dockerfile: build stage runs prisma generate; runtime CMD runs
  prisma migrate deploy before starting the server
- Update CI: add postgres:16-alpine service container and migration steps
  (db:validate, db:generate, db:migrate:prod) before build/test
- Add PrismaService unit test (src/prisma/prisma.service.spec.ts)
- Mock PrismaService in e2e test helper so suites stay DB-free

Closes stellar-vortex-protocol#37
- Add IIntentsRepository interface (save, findById, findAll,
  findByState, findByUser, update) and INTENTS_REPOSITORY Symbol token
  in src/intents/intents.repository.ts
- Add InMemoryIntentsRepository in src/intents/in-memory-intents.repository.ts
  — lifts all Map logic and seed data out of IntentsService
- Refactor IntentsService to pure orchestration: UUID generation,
  default state/deadline live here; all persistence delegated to the
  injected IIntentsRepository
- Update IntentsModule to bind InMemoryIntentsRepository under the
  INTENTS_REPOSITORY token — swap the binding to change storage backend
- Update intents.service.spec.ts to wire service via TestingModule with
  real InMemoryIntentsRepository under the DI token
- Add in-memory-intents.repository.spec.ts — 14 tests covering every
  method including seed, overwrite, case-insensitive user lookup, and
  partial-patch behaviour

All tests pass: 35 unit (5 suites), 23 e2e (5 suites), lint clean,
typecheck clean.

Closes stellar-vortex-protocol#38
- Add DatabaseHealthService: probes via PrismaService.$queryRaw`SELECT 1`,
  races against a 3s timeout, never throws, returns
  { status, latencyMs?, error? }
- Update HealthController: async check(), injects DatabaseHealthService,
  response includes a top-level `db` field
- Update HealthModule: provide DatabaseHealthService (PrismaModule is
  already global so no import needed)
- Update health.e2e-spec.ts: assert db field shape for both the ok and
  unreachable branches — suite passes with the mock PrismaService that
  has no real connection, exercising the graceful-degradation path
- Add database-health.service.spec.ts: 4 unit tests covering the success
  path, query rejection, timeout (fake timers), and missing $queryRaw

Closes stellar-vortex-protocol#39
@drips-wave

drips-wave Bot commented Jul 27, 2026

Copy link
Copy Markdown

@Keengfk Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add datastore connection pooling and health-check wiring

1 participant