@catbee/utils 2.1.1 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/config/index.cjs +5 -6
- package/config/index.mjs +5 -6
- package/healthz-server/index.cjs +42 -5
- package/healthz-server/index.d.ts +49 -23
- package/healthz-server/index.mjs +42 -5
- package/package.json +1 -1
- package/server/index.cjs +180 -101
- package/server/index.d.ts +60 -32
- package/server/index.mjs +183 -104
- package/types/index.d.ts +142 -47
package/server/index.cjs
CHANGED
|
@@ -39,6 +39,7 @@ var fs = require('@catbee/utils/fs');
|
|
|
39
39
|
var validation = require('@catbee/utils/validation');
|
|
40
40
|
var async = require('@catbee/utils/async');
|
|
41
41
|
var id = require('@catbee/utils/id');
|
|
42
|
+
var healthzServer = require('@catbee/utils/healthz-server');
|
|
42
43
|
|
|
43
44
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
44
45
|
|
|
@@ -307,36 +308,53 @@ var ServerConfigBuilder = class {
|
|
|
307
308
|
return this.setEnabled("requestLogging", false);
|
|
308
309
|
}
|
|
309
310
|
/**
|
|
310
|
-
* Configures server
|
|
311
|
+
* Configures the dedicated Healthz probe HTTP server for Kubernetes.
|
|
311
312
|
*
|
|
312
|
-
* @param opts -
|
|
313
|
+
* @param opts - Healthz server configuration options or boolean toggle
|
|
313
314
|
* @returns The builder instance for chaining
|
|
314
|
-
* @default - { path: '/healthz', detailed: true, withGlobalPrefix: false }
|
|
315
315
|
*
|
|
316
316
|
* @example
|
|
317
317
|
* ```typescript
|
|
318
|
-
* builder.
|
|
319
|
-
*
|
|
320
|
-
*
|
|
318
|
+
* builder.withHealthzServer({
|
|
319
|
+
* port: 8282,
|
|
320
|
+
* shutdownDelayMs: 5000,
|
|
321
|
+
* readinessChecks: [
|
|
322
|
+
* { name: 'db', check: () => checkDb() }
|
|
323
|
+
* ]
|
|
321
324
|
* })
|
|
322
325
|
* ```
|
|
323
326
|
*/
|
|
324
|
-
|
|
325
|
-
|
|
327
|
+
withHealthzServer(opts) {
|
|
328
|
+
if (typeof opts === "boolean") {
|
|
329
|
+
this.config.healthzServer = opts;
|
|
330
|
+
} else {
|
|
331
|
+
const current = object.isPlainObject(this.config.healthzServer) ? object.deepClone(this.config.healthzServer) : {};
|
|
332
|
+
this.config.healthzServer = object.deepObjMerge({}, current, {
|
|
333
|
+
enable: true,
|
|
334
|
+
...opts
|
|
335
|
+
});
|
|
336
|
+
}
|
|
326
337
|
return this;
|
|
327
338
|
}
|
|
328
339
|
/**
|
|
329
|
-
* Enables
|
|
330
|
-
*
|
|
340
|
+
* Enables the dedicated Healthz probe HTTP server.
|
|
341
|
+
*
|
|
342
|
+
* @param opts - Optional Healthz server configuration options
|
|
331
343
|
* @returns The builder instance for chaining
|
|
344
|
+
*/
|
|
345
|
+
enableHealthzServer(opts = {}) {
|
|
346
|
+
return this.withHealthzServer({
|
|
347
|
+
...opts,
|
|
348
|
+
enable: true
|
|
349
|
+
});
|
|
350
|
+
}
|
|
351
|
+
/**
|
|
352
|
+
* Disables the dedicated Healthz probe HTTP server.
|
|
332
353
|
*
|
|
333
|
-
* @
|
|
334
|
-
* ```typescript
|
|
335
|
-
* builder.disableHealthCheck()
|
|
336
|
-
* ```
|
|
354
|
+
* @returns The builder instance for chaining
|
|
337
355
|
*/
|
|
338
|
-
|
|
339
|
-
return this.
|
|
356
|
+
disableHealthzServer() {
|
|
357
|
+
return this.withHealthzServer(false);
|
|
340
358
|
}
|
|
341
359
|
/**
|
|
342
360
|
* Configures OpenAPI/Swagger documentation for the API.
|
|
@@ -726,11 +744,12 @@ var ExpressServer = class {
|
|
|
726
744
|
gracefulShutdownRegistered = false;
|
|
727
745
|
/** Map of registered signal listeners for clean teardown */
|
|
728
746
|
signalListeners = /* @__PURE__ */ new Map();
|
|
729
|
-
/**
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
747
|
+
/** Running address info for the Healthz probe server */
|
|
748
|
+
healthzAddress;
|
|
749
|
+
/** Named checks queued for Healthz liveness probe */
|
|
750
|
+
healthzChecks = [];
|
|
751
|
+
/** Named checks queued for Healthz readiness probe */
|
|
752
|
+
healthzReadinessChecks = [];
|
|
734
753
|
/** Promise that resolves when initialization (middleware + routes) is complete */
|
|
735
754
|
initPromise;
|
|
736
755
|
/** In-flight start promise to protect against concurrent start() calls */
|
|
@@ -765,8 +784,19 @@ var ExpressServer = class {
|
|
|
765
784
|
logger.getLogger().error(msg);
|
|
766
785
|
throw new Error(msg);
|
|
767
786
|
}
|
|
768
|
-
if (config
|
|
769
|
-
this.
|
|
787
|
+
if (typeof this.config.healthzServer === "boolean") {
|
|
788
|
+
this.config.healthzServer = {
|
|
789
|
+
...healthzServer.HealthzServer.getDefaultConfig(),
|
|
790
|
+
enable: this.config.healthzServer
|
|
791
|
+
};
|
|
792
|
+
}
|
|
793
|
+
if (this.config.healthzServer && typeof this.config.healthzServer === "object") {
|
|
794
|
+
if (this.config.healthzServer.checks) {
|
|
795
|
+
this.healthzChecks.push(...this.config.healthzServer.checks);
|
|
796
|
+
}
|
|
797
|
+
if (this.config.healthzServer.readinessChecks) {
|
|
798
|
+
this.healthzReadinessChecks.push(...this.config.healthzServer.readinessChecks);
|
|
799
|
+
}
|
|
770
800
|
}
|
|
771
801
|
this.globalPrefix = this.normalizePath(this.config.globalPrefix ?? "", false);
|
|
772
802
|
this.hooks = hooks;
|
|
@@ -1114,10 +1144,6 @@ var ExpressServer = class {
|
|
|
1114
1144
|
* 4. Error handler
|
|
1115
1145
|
*/
|
|
1116
1146
|
async setupRoutes() {
|
|
1117
|
-
const healthCheckPath = this.normalizePath(this.config.healthCheck?.path || "/healthz", this.config.healthCheck?.withGlobalPrefix);
|
|
1118
|
-
this.app.get(healthCheckPath, async (_req, res) => {
|
|
1119
|
-
return this.handleHealthCheckRequest(res);
|
|
1120
|
-
});
|
|
1121
1147
|
this.app.use(this.globalPrefix, this.rootRouter);
|
|
1122
1148
|
await this.runHook("afterRoutes", this.app);
|
|
1123
1149
|
this.app.use((req, res) => {
|
|
@@ -1141,60 +1167,25 @@ var ExpressServer = class {
|
|
|
1141
1167
|
});
|
|
1142
1168
|
}
|
|
1143
1169
|
/**
|
|
1144
|
-
*
|
|
1170
|
+
* Whether the Healthz probe server is enabled.
|
|
1145
1171
|
*/
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
return res.status(httpStatusCodes.HttpStatusCodes.OK).json(new response.SuccessResponse("OK"));
|
|
1150
|
-
}
|
|
1151
|
-
const results = await this.executeHealthChecks();
|
|
1152
|
-
const allOk = results.every((r) => r.status);
|
|
1153
|
-
const status = allOk ? httpStatusCodes.HttpStatusCodes.OK : httpStatusCodes.HttpStatusCodes.SERVICE_UNAVAILABLE;
|
|
1154
|
-
const response$1 = new response.SuccessResponse(allOk ? "OK" : "Service unavailable");
|
|
1155
|
-
if (!allOk) response$1.error = true;
|
|
1156
|
-
if (this.config.healthCheck?.detailed) response$1.data = {
|
|
1157
|
-
checks: results
|
|
1158
|
-
};
|
|
1159
|
-
return res.status(status).json(response$1);
|
|
1160
|
-
} catch {
|
|
1161
|
-
return res.status(httpStatusCodes.HttpStatusCodes.INTERNAL_SERVER_ERROR).json(new exception.InternalServerErrorException("Health check failed"));
|
|
1172
|
+
isHealthzServerEnabled() {
|
|
1173
|
+
if (typeof this.config.healthzServer === "boolean") {
|
|
1174
|
+
return this.config.healthzServer;
|
|
1162
1175
|
}
|
|
1176
|
+
return this.config.healthzServer?.enable === true;
|
|
1163
1177
|
}
|
|
1164
1178
|
/**
|
|
1165
|
-
*
|
|
1179
|
+
* Get the graceful shutdown delay in milliseconds configured for HealthzServer.
|
|
1166
1180
|
*/
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
try {
|
|
1170
|
-
const status = await Promise.resolve(check());
|
|
1171
|
-
return {
|
|
1172
|
-
name,
|
|
1173
|
-
status,
|
|
1174
|
-
error: null
|
|
1175
|
-
};
|
|
1176
|
-
} catch (error) {
|
|
1177
|
-
return {
|
|
1178
|
-
name,
|
|
1179
|
-
status: false,
|
|
1180
|
-
error: error.message
|
|
1181
|
-
};
|
|
1182
|
-
}
|
|
1183
|
-
}));
|
|
1184
|
-
return checkResults.map((result) => {
|
|
1185
|
-
if (result.status === "fulfilled") return result.value;
|
|
1186
|
-
return {
|
|
1187
|
-
name: "unknown",
|
|
1188
|
-
status: false,
|
|
1189
|
-
error: result.reason
|
|
1190
|
-
};
|
|
1191
|
-
});
|
|
1181
|
+
getHealthzShutdownDelay() {
|
|
1182
|
+
return typeof this.config.healthzServer === "object" ? this.config.healthzServer.shutdownDelayMs ?? 0 : 0;
|
|
1192
1183
|
}
|
|
1193
1184
|
/**
|
|
1194
|
-
* Register a new health check function for monitoring service dependencies.
|
|
1185
|
+
* Register a new health check function for monitoring service dependencies on the Healthz probe server.
|
|
1195
1186
|
*
|
|
1196
|
-
*
|
|
1197
|
-
*
|
|
1187
|
+
* By default, external dependencies (DB, Redis, etc.) are registered as `readiness` checks.
|
|
1188
|
+
* Can also be registered as `liveness` or `both`.
|
|
1198
1189
|
*
|
|
1199
1190
|
* Examples:
|
|
1200
1191
|
* - Database connectivity
|
|
@@ -1203,33 +1194,61 @@ var ExpressServer = class {
|
|
|
1203
1194
|
* - Memory/CPU usage checks
|
|
1204
1195
|
*
|
|
1205
1196
|
* @param name Unique identifier for the check (used in detailed responses)
|
|
1206
|
-
* @param check Function returning boolean or Promise<boolean> indicating health
|
|
1197
|
+
* @param check Function returning boolean or Promise<boolean> indicating health (supports optional AbortSignal)
|
|
1198
|
+
* @param options Target probe type ('readiness' | 'liveness' | 'both') or options object
|
|
1207
1199
|
* @returns This instance for method chaining
|
|
1208
1200
|
*/
|
|
1209
|
-
registerHealthCheck(name, check) {
|
|
1210
|
-
|
|
1201
|
+
registerHealthCheck(name, check, options) {
|
|
1202
|
+
const probeType = typeof options === "string" ? options : options?.type ?? "readiness";
|
|
1203
|
+
const namedCheck = {
|
|
1211
1204
|
name,
|
|
1212
1205
|
check
|
|
1213
|
-
}
|
|
1206
|
+
};
|
|
1207
|
+
if (probeType === "liveness" || probeType === "both") {
|
|
1208
|
+
this.healthzChecks.push(namedCheck);
|
|
1209
|
+
}
|
|
1210
|
+
if (probeType === "readiness" || probeType === "both") {
|
|
1211
|
+
this.healthzReadinessChecks.push(namedCheck);
|
|
1212
|
+
}
|
|
1213
|
+
healthzServer.HealthzServer.registerCheck(namedCheck, probeType);
|
|
1214
1214
|
return this;
|
|
1215
1215
|
}
|
|
1216
1216
|
/**
|
|
1217
|
-
*
|
|
1218
|
-
* Useful for readiness probes in deployment tooling.
|
|
1217
|
+
* Mark the service as ready / not-ready for traffic on the Healthz probe server.
|
|
1219
1218
|
*
|
|
1220
|
-
* @
|
|
1219
|
+
* @param ready Whether the service is ready to receive traffic
|
|
1220
|
+
* @returns This instance for method chaining
|
|
1221
1221
|
*/
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1222
|
+
setReady(ready) {
|
|
1223
|
+
healthzServer.HealthzServer.setReady(ready);
|
|
1224
|
+
return this;
|
|
1225
|
+
}
|
|
1226
|
+
/**
|
|
1227
|
+
* Whether the service is currently marked as ready for traffic on the Healthz probe server.
|
|
1228
|
+
*/
|
|
1229
|
+
isReady() {
|
|
1230
|
+
return healthzServer.HealthzServer.isReady();
|
|
1231
|
+
}
|
|
1232
|
+
/**
|
|
1233
|
+
* Get the running HealthzServer instance (if started).
|
|
1234
|
+
*/
|
|
1235
|
+
getHealthzServer() {
|
|
1236
|
+
return healthzServer.HealthzServer.getInstance();
|
|
1237
|
+
}
|
|
1238
|
+
/**
|
|
1239
|
+
* Get the address info of the running HealthzServer (if started).
|
|
1240
|
+
*/
|
|
1241
|
+
getHealthzAddress() {
|
|
1242
|
+
return this.healthzAddress;
|
|
1243
|
+
}
|
|
1244
|
+
/**
|
|
1245
|
+
* Returns whether the service is currently marked as ready for traffic on the Healthz probe server.
|
|
1246
|
+
* Useful for readiness checks in deployment tooling.
|
|
1247
|
+
*
|
|
1248
|
+
* @returns `true` when ready, otherwise `false`.
|
|
1249
|
+
*/
|
|
1250
|
+
ready() {
|
|
1251
|
+
return healthzServer.HealthzServer.isReady();
|
|
1233
1252
|
}
|
|
1234
1253
|
/**
|
|
1235
1254
|
* Get the underlying Express application instance.
|
|
@@ -1299,6 +1318,10 @@ var ExpressServer = class {
|
|
|
1299
1318
|
try {
|
|
1300
1319
|
server.removeAllListeners();
|
|
1301
1320
|
server.close();
|
|
1321
|
+
if (healthzServer.HealthzServer.isStarted()) {
|
|
1322
|
+
healthzServer.HealthzServer.stop().catch(() => {
|
|
1323
|
+
});
|
|
1324
|
+
}
|
|
1302
1325
|
} catch {
|
|
1303
1326
|
}
|
|
1304
1327
|
this.server = null;
|
|
@@ -1313,10 +1336,50 @@ var ExpressServer = class {
|
|
|
1313
1336
|
this.setupConnectionTracking();
|
|
1314
1337
|
Promise.resolve(this.runHook("onServerCreated", server)).then(() => {
|
|
1315
1338
|
const onListening = /* @__PURE__ */ __name(async () => {
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1339
|
+
try {
|
|
1340
|
+
if (this.isHealthzServerEnabled()) {
|
|
1341
|
+
const healthzConfig = {
|
|
1342
|
+
...typeof this.config.healthzServer === "object" ? this.config.healthzServer : {},
|
|
1343
|
+
handleSignals: false,
|
|
1344
|
+
checks: [
|
|
1345
|
+
...this.healthzChecks
|
|
1346
|
+
],
|
|
1347
|
+
readinessChecks: [
|
|
1348
|
+
...this.healthzReadinessChecks
|
|
1349
|
+
]
|
|
1350
|
+
};
|
|
1351
|
+
const addr = await healthzServer.HealthzServer.start(healthzConfig);
|
|
1352
|
+
if (!addr) {
|
|
1353
|
+
throw new Error("Healthz probe server failed to start (already running in this process)");
|
|
1354
|
+
}
|
|
1355
|
+
this.healthzAddress = addr;
|
|
1356
|
+
}
|
|
1357
|
+
this.logServerStartInfo();
|
|
1358
|
+
await this.runHook("afterStart", server);
|
|
1359
|
+
if (this.isHealthzServerEnabled()) {
|
|
1360
|
+
healthzServer.HealthzServer.setReady(true);
|
|
1361
|
+
}
|
|
1362
|
+
isListening = true;
|
|
1363
|
+
resolve(server);
|
|
1364
|
+
} catch (err) {
|
|
1365
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
1366
|
+
logger.getLogger().error({
|
|
1367
|
+
err: error
|
|
1368
|
+
}, "Server startup failed");
|
|
1369
|
+
if (healthzServer.HealthzServer.isStarted()) {
|
|
1370
|
+
await healthzServer.HealthzServer.stop().catch(() => {
|
|
1371
|
+
});
|
|
1372
|
+
}
|
|
1373
|
+
try {
|
|
1374
|
+
server.removeAllListeners();
|
|
1375
|
+
server.close();
|
|
1376
|
+
} catch {
|
|
1377
|
+
}
|
|
1378
|
+
this.server = null;
|
|
1379
|
+
this.healthzAddress = null;
|
|
1380
|
+
this.connections.clear();
|
|
1381
|
+
reject(error);
|
|
1382
|
+
}
|
|
1320
1383
|
}, "onListening");
|
|
1321
1384
|
const listenArgs = [
|
|
1322
1385
|
this.config.port,
|
|
@@ -1367,8 +1430,8 @@ var ExpressServer = class {
|
|
|
1367
1430
|
const host = this.formatHostForUrl(this.config.host || "localhost");
|
|
1368
1431
|
const url = `${protocol}://${host}:${port}`;
|
|
1369
1432
|
logger.getLogger().info(`Server running on ${url}`);
|
|
1370
|
-
if (this.
|
|
1371
|
-
logger.getLogger().info(`
|
|
1433
|
+
if (this.healthzAddress) {
|
|
1434
|
+
logger.getLogger().info(`Healthz probe server running on http://${this.healthzAddress.address}:${this.healthzAddress.port}`);
|
|
1372
1435
|
}
|
|
1373
1436
|
if (this.config.openApi?.enable) {
|
|
1374
1437
|
logger.getLogger().info(`API docs available at ${url}${this.normalizePath(this.config.openApi.mountPath, this.config.openApi.withGlobalPrefix)}`);
|
|
@@ -1391,7 +1454,7 @@ var ExpressServer = class {
|
|
|
1391
1454
|
* - Monitoring systems are notified
|
|
1392
1455
|
*/
|
|
1393
1456
|
async stop(force = false) {
|
|
1394
|
-
if (!this.server) {
|
|
1457
|
+
if (!this.server && !healthzServer.HealthzServer.isStarted()) {
|
|
1395
1458
|
logger.getLogger().warn("Stop called but server is not running");
|
|
1396
1459
|
return;
|
|
1397
1460
|
}
|
|
@@ -1400,10 +1463,26 @@ var ExpressServer = class {
|
|
|
1400
1463
|
return;
|
|
1401
1464
|
}
|
|
1402
1465
|
this.isShuttingDown = true;
|
|
1403
|
-
|
|
1466
|
+
if (healthzServer.HealthzServer.isStarted()) {
|
|
1467
|
+
healthzServer.HealthzServer.setReady(false);
|
|
1468
|
+
}
|
|
1469
|
+
if (this.server) {
|
|
1470
|
+
await this.runHook("beforeStop", this.server);
|
|
1471
|
+
}
|
|
1404
1472
|
try {
|
|
1405
|
-
|
|
1473
|
+
const shutdownDelay = this.getHealthzShutdownDelay();
|
|
1474
|
+
if (shutdownDelay > 0 && !force && healthzServer.HealthzServer.isStarted()) {
|
|
1475
|
+
logger.getLogger().info(`Waiting ${shutdownDelay}ms for load balancer to drain traffic...`);
|
|
1476
|
+
await new Promise((resolve) => setTimeout(resolve, shutdownDelay));
|
|
1477
|
+
}
|
|
1478
|
+
if (this.server) {
|
|
1479
|
+
await this.gracefulShutdown(force);
|
|
1480
|
+
}
|
|
1406
1481
|
} finally {
|
|
1482
|
+
if (healthzServer.HealthzServer.isStarted()) {
|
|
1483
|
+
await healthzServer.HealthzServer.stop();
|
|
1484
|
+
this.healthzAddress = null;
|
|
1485
|
+
}
|
|
1407
1486
|
this.isShuttingDown = false;
|
|
1408
1487
|
}
|
|
1409
1488
|
}
|
|
@@ -1492,7 +1571,7 @@ var ExpressServer = class {
|
|
|
1492
1571
|
logger.getLogger().info(`Received ${signal}, initiating graceful shutdown...`);
|
|
1493
1572
|
try {
|
|
1494
1573
|
this.disableGracefulShutdown();
|
|
1495
|
-
await this.stop(
|
|
1574
|
+
await this.stop(false);
|
|
1496
1575
|
process.exit(0);
|
|
1497
1576
|
} catch (err) {
|
|
1498
1577
|
logger.getLogger().fatal({
|
package/server/index.d.ts
CHANGED
|
@@ -26,6 +26,7 @@ import express, { Express, Router } from 'express';
|
|
|
26
26
|
import http from 'node:http';
|
|
27
27
|
import https from 'node:https';
|
|
28
28
|
import { CatbeeServerConfig, CatbeeServerHooks } from '@catbee/utils/types';
|
|
29
|
+
import { HealthzServer, HealthzAddressInfo, CatbeeHealthzServerConfig } from '@catbee/utils/healthz-server';
|
|
29
30
|
|
|
30
31
|
/**
|
|
31
32
|
* Map of critical dependencies to their error messages.
|
|
@@ -76,11 +77,12 @@ declare class ExpressServer {
|
|
|
76
77
|
private gracefulShutdownRegistered;
|
|
77
78
|
/** Map of registered signal listeners for clean teardown */
|
|
78
79
|
private readonly signalListeners;
|
|
79
|
-
/**
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
80
|
+
/** Running address info for the Healthz probe server */
|
|
81
|
+
private healthzAddress?;
|
|
82
|
+
/** Named checks queued for Healthz liveness probe */
|
|
83
|
+
private readonly healthzChecks;
|
|
84
|
+
/** Named checks queued for Healthz readiness probe */
|
|
85
|
+
private readonly healthzReadinessChecks;
|
|
84
86
|
/** Promise that resolves when initialization (middleware + routes) is complete */
|
|
85
87
|
private readonly initPromise;
|
|
86
88
|
/** In-flight start promise to protect against concurrent start() calls */
|
|
@@ -197,18 +199,18 @@ declare class ExpressServer {
|
|
|
197
199
|
*/
|
|
198
200
|
protected setupRoutes(): Promise<void>;
|
|
199
201
|
/**
|
|
200
|
-
*
|
|
202
|
+
* Whether the Healthz probe server is enabled.
|
|
201
203
|
*/
|
|
202
|
-
|
|
204
|
+
isHealthzServerEnabled(): boolean;
|
|
203
205
|
/**
|
|
204
|
-
*
|
|
206
|
+
* Get the graceful shutdown delay in milliseconds configured for HealthzServer.
|
|
205
207
|
*/
|
|
206
|
-
private
|
|
208
|
+
private getHealthzShutdownDelay;
|
|
207
209
|
/**
|
|
208
|
-
* Register a new health check function for monitoring service dependencies.
|
|
210
|
+
* Register a new health check function for monitoring service dependencies on the Healthz probe server.
|
|
209
211
|
*
|
|
210
|
-
*
|
|
211
|
-
*
|
|
212
|
+
* By default, external dependencies (DB, Redis, etc.) are registered as `readiness` checks.
|
|
213
|
+
* Can also be registered as `liveness` or `both`.
|
|
212
214
|
*
|
|
213
215
|
* Examples:
|
|
214
216
|
* - Database connectivity
|
|
@@ -217,17 +219,39 @@ declare class ExpressServer {
|
|
|
217
219
|
* - Memory/CPU usage checks
|
|
218
220
|
*
|
|
219
221
|
* @param name Unique identifier for the check (used in detailed responses)
|
|
220
|
-
* @param check Function returning boolean or Promise<boolean> indicating health
|
|
222
|
+
* @param check Function returning boolean or Promise<boolean> indicating health (supports optional AbortSignal)
|
|
223
|
+
* @param options Target probe type ('readiness' | 'liveness' | 'both') or options object
|
|
224
|
+
* @returns This instance for method chaining
|
|
225
|
+
*/
|
|
226
|
+
registerHealthCheck(name: string, check: (signal?: AbortSignal) => Promise<boolean> | boolean, options?: 'readiness' | 'liveness' | 'both' | {
|
|
227
|
+
type?: 'readiness' | 'liveness' | 'both';
|
|
228
|
+
}): this;
|
|
229
|
+
/**
|
|
230
|
+
* Mark the service as ready / not-ready for traffic on the Healthz probe server.
|
|
231
|
+
*
|
|
232
|
+
* @param ready Whether the service is ready to receive traffic
|
|
221
233
|
* @returns This instance for method chaining
|
|
222
234
|
*/
|
|
223
|
-
|
|
235
|
+
setReady(ready: boolean): this;
|
|
236
|
+
/**
|
|
237
|
+
* Whether the service is currently marked as ready for traffic on the Healthz probe server.
|
|
238
|
+
*/
|
|
239
|
+
isReady(): boolean;
|
|
240
|
+
/**
|
|
241
|
+
* Get the running HealthzServer instance (if started).
|
|
242
|
+
*/
|
|
243
|
+
getHealthzServer(): HealthzServer | undefined;
|
|
244
|
+
/**
|
|
245
|
+
* Get the address info of the running HealthzServer (if started).
|
|
246
|
+
*/
|
|
247
|
+
getHealthzAddress(): HealthzAddressInfo | null | undefined;
|
|
224
248
|
/**
|
|
225
|
-
*
|
|
226
|
-
* Useful for readiness
|
|
249
|
+
* Returns whether the service is currently marked as ready for traffic on the Healthz probe server.
|
|
250
|
+
* Useful for readiness checks in deployment tooling.
|
|
227
251
|
*
|
|
228
|
-
* @returns
|
|
252
|
+
* @returns `true` when ready, otherwise `false`.
|
|
229
253
|
*/
|
|
230
|
-
ready():
|
|
254
|
+
ready(): boolean;
|
|
231
255
|
/**
|
|
232
256
|
* Get the underlying Express application instance.
|
|
233
257
|
* Use this for advanced Express features not exposed by this wrapper.
|
|
@@ -715,32 +739,36 @@ declare class ServerConfigBuilder {
|
|
|
715
739
|
*/
|
|
716
740
|
disableRequestLogging(): this;
|
|
717
741
|
/**
|
|
718
|
-
* Configures server
|
|
742
|
+
* Configures the dedicated Healthz probe HTTP server for Kubernetes.
|
|
719
743
|
*
|
|
720
|
-
* @param opts -
|
|
744
|
+
* @param opts - Healthz server configuration options or boolean toggle
|
|
721
745
|
* @returns The builder instance for chaining
|
|
722
|
-
* @default - { path: '/healthz', detailed: true, withGlobalPrefix: false }
|
|
723
746
|
*
|
|
724
747
|
* @example
|
|
725
748
|
* ```typescript
|
|
726
|
-
* builder.
|
|
727
|
-
*
|
|
728
|
-
*
|
|
749
|
+
* builder.withHealthzServer({
|
|
750
|
+
* port: 8282,
|
|
751
|
+
* shutdownDelayMs: 5000,
|
|
752
|
+
* readinessChecks: [
|
|
753
|
+
* { name: 'db', check: () => checkDb() }
|
|
754
|
+
* ]
|
|
729
755
|
* })
|
|
730
756
|
* ```
|
|
731
757
|
*/
|
|
732
|
-
|
|
758
|
+
withHealthzServer(opts: NonNullable<CatbeeServerConfig['healthzServer']>): this;
|
|
733
759
|
/**
|
|
734
|
-
* Enables
|
|
735
|
-
*
|
|
760
|
+
* Enables the dedicated Healthz probe HTTP server.
|
|
761
|
+
*
|
|
762
|
+
* @param opts - Optional Healthz server configuration options
|
|
736
763
|
* @returns The builder instance for chaining
|
|
764
|
+
*/
|
|
765
|
+
enableHealthzServer(opts?: Partial<CatbeeHealthzServerConfig>): this;
|
|
766
|
+
/**
|
|
767
|
+
* Disables the dedicated Healthz probe HTTP server.
|
|
737
768
|
*
|
|
738
|
-
* @
|
|
739
|
-
* ```typescript
|
|
740
|
-
* builder.disableHealthCheck()
|
|
741
|
-
* ```
|
|
769
|
+
* @returns The builder instance for chaining
|
|
742
770
|
*/
|
|
743
|
-
|
|
771
|
+
disableHealthzServer(): this;
|
|
744
772
|
/**
|
|
745
773
|
* Configures OpenAPI/Swagger documentation for the API.
|
|
746
774
|
*
|