kozminski

@kozminski/dbhealth (1.0.1)

Published 2026-09-11 19:46:39 +02:00 by wiktor

Installation

@kozminski:registry=https://git.kozminski.net.pl/api/packages/kozminski/npm/
npm install @kozminski/dbhealth@1.0.1
"@kozminski/dbhealth": "1.0.1"

About this package

Active database health probe with express-compatible handler and self-healing callback

@kozminski/dbhealth

Aktywny monitor kondycji połączenia z bazą dla usług backendu. Daje handler /health zgodny z express oraz callback pozwalający usłudze naprawić się samodzielnie (np. process.exit(1), gdy kontener ma restart: unless-stopped).

Po co to jest

11.09.2026 o 15:30 w replica secie solis_set odbyły się wybory nowego węzła głównego. Sterownik Mongo wewnątrz działającego procesu orders-service nie odbudował topologii — przez dwie godziny każde zapytanie kończyło się MongoServerSelectionError, a mimo to HEALTHCHECK kontenera (odpytujący GET /) raportował usługę jako sprawną, więc nginx dalej kierował tam ruch. Naprawił to dopiero ręczny restart kontenera.

Dlatego monitor nie sprawdza readyState — przy tej awarii połączenie było formalnie otwarte, tylko bezużyteczne, i w logach nie było żadnego zdarzenia rozłączenia. Zamiast tego wykonuje realne zapytanie (ping) z własnym limitem czasu, co wykrywa zarówno zerwane połączenie, jak i połączenie żywe, lecz niezdolne wybrać serwera.

Paczka nie zależy od mongoose ani od express (działa z mongoose 5.x, 6.x i 7.x) i nie ma żadnych zależności.

Użycie

const mongoose = require('mongoose');
const { createMonitor } = require('@kozminski/dbhealth');
const logger = require('./src/Logger.js');

const monitor = createMonitor({
    connection: mongoose.connection,
    logger,
    onUnhealthy({ downMs, error }) {
        logger.error('orders.main.db_health.exiting', { downMs, error: error.message });
        process.exit(1); // Docker (unless-stopped) podniesie kontener z czystym stanem
    }
});

module.exports = monitor;

Trasę montujemy przed middleware'ami autoryzacji, inaczej healthcheck dostanie 401:

app.get('/health', require('../src/DbHealth.js').handler);

W Dockerfile:

HEALTHCHECK --interval=30s --timeout=5s --start-period=30s --retries=3 \
    CMD node -e "fetch('http://127.0.0.1:'+(process.env.APP_PORT||3000)+'/health').then(r=>process.exit(r.status===200?0:1)).catch(()=>process.exit(1))"

Opcje

Opcja Domyślnie Opis
connection Wymagane. Połączenie mongoose (mongoose.connection).
logger brak logów Obiekt { info, warn, error }, np. winston.
probeIntervalMs 15000 Co ile milisekund sondować bazę.
probeTimeoutMs 5000 Limit czasu jednej sondy. Bez niego ping czekałby 30 s (mongoose 6) albo w nieskończoność (mongoose 5).
gracePeriodMs 90000 Po ilu ms nieprzerwanej awarii wołamy onUnhealthy.
onUnhealthy brak Callback ({ downMs, error }) wołany dokładnie raz na awarię (kolejny raz dopiero po odzyskaniu połączenia).

API monitora

  • monitor.handler(req, res), handler zgodny z express (używa wyłącznie API node'owego res). Zwraca 200 { status: 'ok', lastOkAt } albo 503 { status: 'db-unavailable', lastOkAt, downMs, error }.
  • monitor.isHealthy()true/false.
  • monitor.stop() — zatrzymuje sondę.

Zachowanie

  • Pierwsza sonda odpala się od razu przy tworzeniu monitora, a lastOkAt startuje z Date.now(), dzięki czemu okno karencji obejmuje też pierwsze łączenie po starcie usługi.
  • Brak connection.db (jeszcze nie połączono) liczy się jak nieudana sonda.
  • Timer interwału jest unref(), więc monitor nie trzyma procesu przy życiu.
  • Logi: dbhealth.probe_failed (warn) przy każdej nieudanej sondzie, dbhealth.recovered (info) przy powrocie do zdrowia.

Keywords

health mongo
Details
npm
2026-09-11 19:46:39 +02:00
4
kozminski.net.pl
ISC
latest
3.9 KiB
Assets (1)
Versions (2) View all
1.0.1 2026-09-11
1.0.0 2026-09-11