@autofleet/nitur 2.2.0 → 2.2.1-1
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/lib/_virtual/rolldown_runtime.cjs +1 -1
- package/lib/alive-endpoint/base.cjs +1 -1
- package/lib/alive-endpoint/base.cjs.map +1 -1
- package/lib/alive-endpoint/base.js +1 -1
- package/lib/alive-endpoint/base.js.map +1 -1
- package/lib/alive-endpoint/middleware.cjs +1 -1
- package/lib/alive-endpoint/middleware.cjs.map +1 -1
- package/lib/alive-endpoint/middleware.js +1 -1
- package/lib/alive-endpoint/middleware.js.map +1 -1
- package/lib/health/liveness.cjs +2 -0
- package/lib/health/liveness.cjs.map +1 -0
- package/lib/health/liveness.d.cts +10 -0
- package/lib/health/liveness.d.ts +10 -0
- package/lib/health/liveness.js +2 -0
- package/lib/health/liveness.js.map +1 -0
- package/lib/health/readiness.cjs +2 -0
- package/lib/health/readiness.cjs.map +1 -0
- package/lib/health/readiness.d.cts +24 -0
- package/lib/health/readiness.d.ts +24 -0
- package/lib/health/readiness.js +2 -0
- package/lib/health/readiness.js.map +1 -0
- package/lib/health/shared.cjs +2 -0
- package/lib/health/shared.cjs.map +1 -0
- package/lib/health/shared.d.cts +9 -0
- package/lib/health/shared.d.ts +9 -0
- package/lib/health/shared.js +2 -0
- package/lib/health/shared.js.map +1 -0
- package/lib/index.cjs +2 -1
- package/lib/index.cjs.map +1 -0
- package/lib/index.d.cts +11 -3
- package/lib/index.d.ts +11 -3
- package/lib/index.js +2 -1
- package/lib/index.js.map +1 -0
- package/lib/logger/src/index.d.cts +31 -0
- package/lib/logger/src/index.d.ts +31 -0
- package/lib/logger.cjs +1 -1
- package/lib/logger.cjs.map +1 -1
- package/lib/logger.d.cts +1 -1
- package/lib/logger.d.ts +1 -1
- package/package.json +11 -10
- package/lib/health-manager/health-check-handlers.cjs +0 -2
- package/lib/health-manager/health-check-handlers.cjs.map +0 -1
- package/lib/health-manager/health-check-handlers.js +0 -2
- package/lib/health-manager/health-check-handlers.js.map +0 -1
- package/lib/health-manager/health-manager.cjs +0 -2
- package/lib/health-manager/health-manager.cjs.map +0 -1
- package/lib/health-manager/health-manager.d.cts +0 -88
- package/lib/health-manager/health-manager.d.ts +0 -88
- package/lib/health-manager/health-manager.js +0 -2
- package/lib/health-manager/health-manager.js.map +0 -1
- package/lib/health-manager/shutdown-handlers.cjs +0 -2
- package/lib/health-manager/shutdown-handlers.cjs.map +0 -1
- package/lib/health-manager/shutdown-handlers.js +0 -2
- package/lib/health-manager/shutdown-handlers.js.map +0 -1
- package/lib/health-manager/types.cjs +0 -2
- package/lib/health-manager/types.cjs.map +0 -1
- package/lib/health-manager/types.d.cts +0 -113
- package/lib/health-manager/types.d.ts +0 -113
- package/lib/health-manager/types.js +0 -2
- package/lib/health-manager/types.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
var e=Object.create,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,o=(e,i,o,s)=>{if(i&&typeof i==`object`||typeof i==`function`)for(var c=r(i),l=0,u=c.length,d;l<u;l++)d=c[l],!a.call(e,d)&&d!==o&&t(e,d,{get:(e=>i[e]).bind(null,d),enumerable:!(s=n(i,d))||s.enumerable});return e},s=(n,r,a)=>(a=n==null?{}:e(i(n)),o(r||!n||!n.__esModule?t(a,`default`,{value:n,enumerable:!0}):a,n));exports
|
|
1
|
+
var e=Object.create,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,o=(e,i,o,s)=>{if(i&&typeof i==`object`||typeof i==`function`)for(var c=r(i),l=0,u=c.length,d;l<u;l++)d=c[l],!a.call(e,d)&&d!==o&&t(e,d,{get:(e=>i[e]).bind(null,d),enumerable:!(s=n(i,d))||s.enumerable});return e},s=(n,r,a)=>(a=n==null?{}:e(i(n)),o(r||!n||!n.__esModule?t(a,`default`,{value:n,enumerable:!0}):a,n));Object.defineProperty(exports,`__toESM`,{enumerable:!0,get:function(){return s}});
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
async function e({rabbit:e=null,sequelize:t=null,redis:n=null,elasticsearch:r=null}){if(e
|
|
1
|
+
async function e({rabbit:e=null,sequelize:t=null,redis:n=null,elasticsearch:r=null}){if(e){let t=await e.isConnected();if(!t)throw Error(`Rabbit is not alive`)}if(t){let[[{status:e}]]=await t.query(`select 'ok' as status`);if(e!==`ok`)throw Error(`Sequelize is not alive`)}return n&&await n.ping(),r&&await r.ping(),{status:`ok`}}exports.systemAliveCheck=e;
|
|
2
2
|
//# sourceMappingURL=base.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base.cjs","names":[],"sources":["../../src/alive-endpoint/base.ts"],"sourcesContent":["import type { logger as loggerFallback } from '../logger';\n\nexport interface SystemAliveParameters {\n rabbit?: null | { isConnected: () => PromiseLike<boolean>; };\n sequelize?: null | { query(sql: string | { query: string; values: unknown[]; }): PromiseLike<any>; };\n redis?: null | { ping: () => Promise<void>; };\n elasticsearch?: null | { ping: () => Promise<boolean>; };\n logger?: typeof loggerFallback;\n}\n\nexport async function systemAliveCheck({\n rabbit = null,\n sequelize = null,\n redis = null,\n elasticsearch = null,\n}: SystemAliveParameters): Promise<{ status: 'ok'; }> {\n if (rabbit) {\n const isRabbitAlive = await rabbit.isConnected();\n if (!isRabbitAlive) {\n throw new Error('Rabbit is not alive');\n }\n }\n\n if (sequelize) {\n const [[{ status }]] = await sequelize.query('select \\'ok\\' as status');\n if (status !== 'ok') {\n throw new Error('Sequelize is not alive');\n }\n }\n\n if (redis) {\n await redis.ping();\n }\n\n if (elasticsearch) {\n await elasticsearch.ping();\n }\n\n return { status: 'ok' };\n};\n"],"mappings":"AAUA,eAAsB,EAAiB,CACrC,SAAS,KACT,YAAY,KACZ,QAAQ,KACR,gBAAgB,
|
|
1
|
+
{"version":3,"file":"base.cjs","names":[],"sources":["../../src/alive-endpoint/base.ts"],"sourcesContent":["import type { logger as loggerFallback } from '../logger';\n\nexport interface SystemAliveParameters {\n rabbit?: null | { isConnected: () => PromiseLike<boolean>; };\n sequelize?: null | { query(sql: string | { query: string; values: unknown[]; }): PromiseLike<any>; };\n redis?: null | { ping: () => Promise<void>; };\n elasticsearch?: null | { ping: () => Promise<boolean>; };\n logger?: typeof loggerFallback;\n}\n\nexport async function systemAliveCheck({\n rabbit = null,\n sequelize = null,\n redis = null,\n elasticsearch = null,\n}: SystemAliveParameters): Promise<{ status: 'ok'; }> {\n if (rabbit) {\n const isRabbitAlive = await rabbit.isConnected();\n if (!isRabbitAlive) {\n throw new Error('Rabbit is not alive');\n }\n }\n\n if (sequelize) {\n const [[{ status }]] = await sequelize.query('select \\'ok\\' as status');\n if (status !== 'ok') {\n throw new Error('Sequelize is not alive');\n }\n }\n\n if (redis) {\n await redis.ping();\n }\n\n if (elasticsearch) {\n await elasticsearch.ping();\n }\n\n return { status: 'ok' };\n};\n"],"mappings":"AAUA,eAAsB,EAAiB,CACrC,SAAS,KACT,YAAY,KACZ,QAAQ,KACR,gBAAgB,KACM,CAA8B,CACpD,GAAI,EAAQ,CACV,IAAM,EAAgB,KAAM,GAAO,aAAa,CAChD,IAAK,EACH,KAAM,CAAI,MAAM,sBAAA,AAEnB,CAED,GAAI,EAAW,CACb,GAAM,CAAC,CAAC,CAAE,SAAQ,CAAC,CAAC,CAAG,KAAM,GAAU,MAAM,wBAA0B,CACvE,GAAI,IAAW,KACb,KAAM,CAAI,MAAM,yBAAA,AAEnB,CAUD,OARI,GACF,KAAM,GAAM,MAAM,CAGhB,GACF,KAAM,GAAc,MAAM,CAGrB,CAAE,OAAQ,IAAM,CACxB"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
async function e({rabbit:e=null,sequelize:t=null,redis:n=null,elasticsearch:r=null}){if(e
|
|
1
|
+
async function e({rabbit:e=null,sequelize:t=null,redis:n=null,elasticsearch:r=null}){if(e){let t=await e.isConnected();if(!t)throw Error(`Rabbit is not alive`)}if(t){let[[{status:e}]]=await t.query(`select 'ok' as status`);if(e!==`ok`)throw Error(`Sequelize is not alive`)}return n&&await n.ping(),r&&await r.ping(),{status:`ok`}}export{e as systemAliveCheck};
|
|
2
2
|
//# sourceMappingURL=base.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base.js","names":[],"sources":["../../src/alive-endpoint/base.ts"],"sourcesContent":["import type { logger as loggerFallback } from '../logger';\n\nexport interface SystemAliveParameters {\n rabbit?: null | { isConnected: () => PromiseLike<boolean>; };\n sequelize?: null | { query(sql: string | { query: string; values: unknown[]; }): PromiseLike<any>; };\n redis?: null | { ping: () => Promise<void>; };\n elasticsearch?: null | { ping: () => Promise<boolean>; };\n logger?: typeof loggerFallback;\n}\n\nexport async function systemAliveCheck({\n rabbit = null,\n sequelize = null,\n redis = null,\n elasticsearch = null,\n}: SystemAliveParameters): Promise<{ status: 'ok'; }> {\n if (rabbit) {\n const isRabbitAlive = await rabbit.isConnected();\n if (!isRabbitAlive) {\n throw new Error('Rabbit is not alive');\n }\n }\n\n if (sequelize) {\n const [[{ status }]] = await sequelize.query('select \\'ok\\' as status');\n if (status !== 'ok') {\n throw new Error('Sequelize is not alive');\n }\n }\n\n if (redis) {\n await redis.ping();\n }\n\n if (elasticsearch) {\n await elasticsearch.ping();\n }\n\n return { status: 'ok' };\n};\n"],"mappings":"AAUA,eAAsB,EAAiB,CACrC,SAAS,KACT,YAAY,KACZ,QAAQ,KACR,gBAAgB,
|
|
1
|
+
{"version":3,"file":"base.js","names":[],"sources":["../../src/alive-endpoint/base.ts"],"sourcesContent":["import type { logger as loggerFallback } from '../logger';\n\nexport interface SystemAliveParameters {\n rabbit?: null | { isConnected: () => PromiseLike<boolean>; };\n sequelize?: null | { query(sql: string | { query: string; values: unknown[]; }): PromiseLike<any>; };\n redis?: null | { ping: () => Promise<void>; };\n elasticsearch?: null | { ping: () => Promise<boolean>; };\n logger?: typeof loggerFallback;\n}\n\nexport async function systemAliveCheck({\n rabbit = null,\n sequelize = null,\n redis = null,\n elasticsearch = null,\n}: SystemAliveParameters): Promise<{ status: 'ok'; }> {\n if (rabbit) {\n const isRabbitAlive = await rabbit.isConnected();\n if (!isRabbitAlive) {\n throw new Error('Rabbit is not alive');\n }\n }\n\n if (sequelize) {\n const [[{ status }]] = await sequelize.query('select \\'ok\\' as status');\n if (status !== 'ok') {\n throw new Error('Sequelize is not alive');\n }\n }\n\n if (redis) {\n await redis.ping();\n }\n\n if (elasticsearch) {\n await elasticsearch.ping();\n }\n\n return { status: 'ok' };\n};\n"],"mappings":"AAUA,eAAsB,EAAiB,CACrC,SAAS,KACT,YAAY,KACZ,QAAQ,KACR,gBAAgB,KACM,CAA8B,CACpD,GAAI,EAAQ,CACV,IAAM,EAAgB,KAAM,GAAO,aAAa,CAChD,IAAK,EACH,KAAM,CAAI,MAAM,sBAAA,AAEnB,CAED,GAAI,EAAW,CACb,GAAM,CAAC,CAAC,CAAE,SAAQ,CAAC,CAAC,CAAG,KAAM,GAAU,MAAM,wBAA0B,CACvE,GAAI,IAAW,KACb,KAAM,CAAI,MAAM,yBAAA,AAEnB,CAUD,OARI,GACF,KAAM,GAAM,MAAM,CAGhB,GACF,KAAM,GAAc,MAAM,CAGrB,CAAE,OAAQ,IAAM,CACxB"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const e=require(
|
|
1
|
+
const e=require(`./base.cjs`),t=require(`../logger.cjs`);function n(n){let r=n.logger??t.logger;return async(t,i)=>{try{let t=await e.systemAliveCheck(n);return i.json(t),!0}catch(e){return i.status(500).json({err:e}),r.error(`Error on alive endpoint`,{err:e}),!1}}}exports.aliveEndpointMiddleware=n;
|
|
2
2
|
//# sourceMappingURL=middleware.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"middleware.cjs","names":["logger","loggerFallback","
|
|
1
|
+
{"version":3,"file":"middleware.cjs","names":["parameters: SystemAliveParameters","logger","loggerFallback","_req: Request","res: Response"],"sources":["../../src/alive-endpoint/middleware.ts"],"sourcesContent":["import type { Request, Response } from 'express';\nimport { logger as loggerFallback } from '../logger';\nimport { systemAliveCheck, type SystemAliveParameters } from './base';\n\nexport function aliveEndpointMiddleware(parameters: SystemAliveParameters) {\n const logger = parameters.logger ?? loggerFallback;\n return async (_req: Request, res: Response): Promise<boolean> => {\n try {\n const response = await systemAliveCheck(parameters);\n res.json(response);\n return true;\n } catch (err) {\n res.status(500).json({ err });\n logger.error('Error on alive endpoint', { err });\n return false;\n }\n };\n}\n"],"mappings":"yDAIA,SAAgB,EAAwBA,EAAmC,CACzE,IAAMC,EAAS,EAAW,QAAUC,EAAAA,OACpC,OAAO,MAAOC,EAAeC,IAAoC,CAC/D,GAAI,CACF,IAAM,EAAW,KAAM,GAAA,iBAAiB,EAAW,CAEnD,MADA,GAAI,KAAK,EAAS,EACX,CACR,OAAQ,EAAK,CAGZ,MAFA,GAAI,OAAO,IAAI,CAAC,KAAK,CAAE,KAAK,EAAC,CAC7B,EAAO,MAAM,0BAA2B,CAAE,KAAK,EAAC,EACzC,CACR,CACF,CACF"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{systemAliveCheck as e}from"./base.js";import{logger as t}from"../logger.js";function n(n){let r=n.logger??t;return async(t,i)=>{try{let t=await e(n);return i.json(t),!0}catch(e){return i.status(500).json({err:e}),r.error(`Error on alive endpoint`,{err:e}),!1}}}export{n as aliveEndpointMiddleware};
|
|
2
2
|
//# sourceMappingURL=middleware.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"middleware.js","names":["logger","loggerFallback"],"sources":["../../src/alive-endpoint/middleware.ts"],"sourcesContent":["import type { Request, Response } from 'express';\nimport { logger as loggerFallback } from '../logger';\nimport { systemAliveCheck, type SystemAliveParameters } from './base';\n\nexport function aliveEndpointMiddleware(parameters: SystemAliveParameters) {\n const logger = parameters.logger ?? loggerFallback;\n return async (_req: Request, res: Response): Promise<boolean> => {\n try {\n const response = await systemAliveCheck(parameters);\n res.json(response);\n return true;\n } catch (err) {\n res.status(500).json({ err });\n logger.error('Error on alive endpoint', { err });\n return false;\n }\n };\n}\n"],"mappings":"mFAIA,SAAgB,
|
|
1
|
+
{"version":3,"file":"middleware.js","names":["parameters: SystemAliveParameters","logger","loggerFallback","_req: Request","res: Response"],"sources":["../../src/alive-endpoint/middleware.ts"],"sourcesContent":["import type { Request, Response } from 'express';\nimport { logger as loggerFallback } from '../logger';\nimport { systemAliveCheck, type SystemAliveParameters } from './base';\n\nexport function aliveEndpointMiddleware(parameters: SystemAliveParameters) {\n const logger = parameters.logger ?? loggerFallback;\n return async (_req: Request, res: Response): Promise<boolean> => {\n try {\n const response = await systemAliveCheck(parameters);\n res.json(response);\n return true;\n } catch (err) {\n res.status(500).json({ err });\n logger.error('Error on alive endpoint', { err });\n return false;\n }\n };\n}\n"],"mappings":"mFAIA,SAAgB,EAAwBA,EAAmC,CACzE,IAAMC,EAAS,EAAW,QAAUC,EACpC,OAAO,MAAOC,EAAeC,IAAoC,CAC/D,GAAI,CACF,IAAM,EAAW,KAAM,GAAiB,EAAW,CAEnD,MADA,GAAI,KAAK,EAAS,EACX,CACR,OAAQ,EAAK,CAGZ,MAFA,GAAI,OAAO,IAAI,CAAC,KAAK,CAAE,KAAK,EAAC,CAC7B,EAAO,MAAM,0BAA2B,CAAE,KAAK,EAAC,EACzC,CACR,CACF,CACF"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const e=require(`../logger.cjs`),t=require(`./shared.cjs`);function n(n){let r=n?.logger??e.logger;return async(e,n)=>{try{return await t.eventLoopHeartbeat(),n.json({status:`alive`}),!0}catch(e){return r.error(`Liveness failed`,{err:e}),n.status(500).json({err:e.message}),!1}}}exports.livenessEndpoint=n;
|
|
2
|
+
//# sourceMappingURL=liveness.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"liveness.cjs","names":["options?: { logger?: SimpleLogger; }","logger","fallbackLogger","_req: Request","res: Response"],"sources":["../../src/health/liveness.ts"],"sourcesContent":["import type { Request, Response } from 'express';\nimport { logger as fallbackLogger } from '../logger';\nimport { eventLoopHeartbeat } from './shared';\nimport type { SimpleLogger } from './shared';\n\nexport function livenessEndpoint(options?: { logger?: SimpleLogger; }) {\n const logger = options?.logger ?? fallbackLogger;\n\n return async (_req: Request, res: Response): Promise<boolean> => {\n try {\n await eventLoopHeartbeat();\n res.json({ status: 'alive' });\n return true;\n } catch (err) {\n logger.error('Liveness failed', { err });\n res.status(500).json({ err: (err as Error).message });\n return false;\n }\n };\n}\n"],"mappings":"2DAKA,SAAgB,EAAiBA,EAAsC,CACrE,IAAMC,EAAS,GAAS,QAAUC,EAAAA,OAElC,OAAO,MAAOC,EAAeC,IAAoC,CAC/D,GAAI,CAGF,OAFA,KAAM,GAAA,oBAAoB,CAC1B,EAAI,KAAK,CAAE,OAAQ,OAAS,EAAC,EACtB,CACR,OAAQ,EAAK,CAGZ,MAFA,GAAO,MAAM,kBAAmB,CAAE,KAAK,EAAC,CACxC,EAAI,OAAO,IAAI,CAAC,KAAK,CAAE,IAAM,EAAc,OAAS,EAAC,EAC9C,CACR,CACF,CACF"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { SimpleLogger } from "./shared.cjs";
|
|
2
|
+
import { Request, Response } from "express";
|
|
3
|
+
|
|
4
|
+
//#region src/health/liveness.d.ts
|
|
5
|
+
declare function livenessEndpoint(options?: {
|
|
6
|
+
logger?: SimpleLogger;
|
|
7
|
+
}): (_req: Request, res: Response) => Promise<boolean>;
|
|
8
|
+
//#endregion
|
|
9
|
+
export { livenessEndpoint };
|
|
10
|
+
//# sourceMappingURL=liveness.d.cts.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { SimpleLogger } from "./shared.js";
|
|
2
|
+
import { Request, Response } from "express";
|
|
3
|
+
|
|
4
|
+
//#region src/health/liveness.d.ts
|
|
5
|
+
declare function livenessEndpoint(options?: {
|
|
6
|
+
logger?: SimpleLogger;
|
|
7
|
+
}): (_req: Request, res: Response) => Promise<boolean>;
|
|
8
|
+
//#endregion
|
|
9
|
+
export { livenessEndpoint };
|
|
10
|
+
//# sourceMappingURL=liveness.d.ts.map
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{logger as e}from"../logger.js";import{eventLoopHeartbeat as t}from"./shared.js";function n(n){let r=n?.logger??e;return async(e,n)=>{try{return await t(),n.json({status:`alive`}),!0}catch(e){return r.error(`Liveness failed`,{err:e}),n.status(500).json({err:e.message}),!1}}}export{n as livenessEndpoint};
|
|
2
|
+
//# sourceMappingURL=liveness.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"liveness.js","names":["options?: { logger?: SimpleLogger; }","logger","fallbackLogger","_req: Request","res: Response"],"sources":["../../src/health/liveness.ts"],"sourcesContent":["import type { Request, Response } from 'express';\nimport { logger as fallbackLogger } from '../logger';\nimport { eventLoopHeartbeat } from './shared';\nimport type { SimpleLogger } from './shared';\n\nexport function livenessEndpoint(options?: { logger?: SimpleLogger; }) {\n const logger = options?.logger ?? fallbackLogger;\n\n return async (_req: Request, res: Response): Promise<boolean> => {\n try {\n await eventLoopHeartbeat();\n res.json({ status: 'alive' });\n return true;\n } catch (err) {\n logger.error('Liveness failed', { err });\n res.status(500).json({ err: (err as Error).message });\n return false;\n }\n };\n}\n"],"mappings":"uFAKA,SAAgB,EAAiBA,EAAsC,CACrE,IAAMC,EAAS,GAAS,QAAUC,EAElC,OAAO,MAAOC,EAAeC,IAAoC,CAC/D,GAAI,CAGF,OAFA,KAAM,IAAoB,CAC1B,EAAI,KAAK,CAAE,OAAQ,OAAS,EAAC,EACtB,CACR,OAAQ,EAAK,CAGZ,MAFA,GAAO,MAAM,kBAAmB,CAAE,KAAK,EAAC,CACxC,EAAI,OAAO,IAAI,CAAC,KAAK,CAAE,IAAM,EAAc,OAAS,EAAC,EAC9C,CACR,CACF,CACF"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const e=require(`../logger.cjs`),t=require(`./shared.cjs`);function n(n){let{rabbit:r,sequelize:i,redis:a,elasticsearch:o,timeoutMs:s=400,logger:c=e.logger}=n;return async(e,n)=>{try{await t.eventLoopHeartbeat();let e=[];return r&&e.push(r.isConnected().then(e=>e||Promise.reject(Error(`Rabbit`)))),i&&e.push(i.authenticate()),a&&e.push(a.ping()),o&&e.push(o.ping()),await t.runParallelChecks(e,s),n.json({status:`ready`}),!0}catch(e){return c.warn?.(`Readiness failed`,{err:e}),n.status(503).json({err:e.message}),!1}}}exports.readinessEndpoint=n;
|
|
2
|
+
//# sourceMappingURL=readiness.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"readiness.cjs","names":["deps: ReadinessDeps","fallbackLogger","_req: Request","res: Response","checks: Promise<unknown>[]"],"sources":["../../src/health/readiness.ts"],"sourcesContent":["import type { Request, Response } from 'express';\nimport { logger as fallbackLogger } from '../logger';\nimport {\n eventLoopHeartbeat,\n runParallelChecks,\n type SimpleLogger,\n} from './shared';\n\nexport interface ReadinessDeps {\n rabbit?: { isConnected: () => Promise<boolean>; };\n sequelize?: { authenticate: () => Promise<void>; };\n redis?: { ping: () => Promise<void>; };\n elasticsearch?: { ping: () => Promise<boolean>; };\n timeoutMs?: number;\n logger?: SimpleLogger;\n}\n\nexport function readinessEndpoint(deps: ReadinessDeps) {\n const {\n rabbit,\n sequelize,\n redis,\n elasticsearch,\n timeoutMs = 400,\n logger = fallbackLogger,\n } = deps;\n\n return async (_req: Request, res: Response): Promise<boolean> => {\n try {\n await eventLoopHeartbeat();\n\n const checks: Promise<unknown>[] = [];\n if (rabbit) checks.push(rabbit.isConnected().then(ok => ok ? ok : Promise.reject(new Error('Rabbit'))));\n if (sequelize) checks.push(sequelize.authenticate());\n if (redis) checks.push(redis.ping());\n if (elasticsearch) checks.push(elasticsearch.ping());\n\n await runParallelChecks(checks, timeoutMs);\n res.json({ status: 'ready' });\n return true;\n } catch (err) {\n logger.warn?.('Readiness failed', { err });\n res.status(503).json({ err: (err as Error).message });\n return false;\n }\n };\n}\n"],"mappings":"2DAiBA,SAAgB,EAAkBA,EAAqB,CACrD,GAAM,CACJ,SACA,YACA,QACA,gBACA,YAAY,IACZ,OAAA,EAASC,EAAAA,OACV,CAAG,EAEJ,OAAO,MAAOC,EAAeC,IAAoC,CAC/D,GAAI,CACF,KAAM,GAAA,oBAAoB,CAE1B,IAAMC,EAA6B,CAAE,EAQrC,OAPI,GAAQ,EAAO,KAAK,EAAO,aAAa,CAAC,KAAK,GAAM,GAAU,QAAQ,OAAO,AAAI,MAAM,SAAA,CAAU,CAAC,CAAC,CACnG,GAAW,EAAO,KAAK,EAAU,cAAc,CAAC,CAChD,GAAO,EAAO,KAAK,EAAM,MAAM,CAAC,CAChC,GAAe,EAAO,KAAK,EAAc,MAAM,CAAC,CAEpD,KAAM,GAAA,kBAAkB,EAAQ,EAAU,CAC1C,EAAI,KAAK,CAAE,OAAQ,OAAS,EAAC,EACtB,CACR,OAAQ,EAAK,CAGZ,MAFA,GAAO,OAAO,mBAAoB,CAAE,KAAK,EAAC,CAC1C,EAAI,OAAO,IAAI,CAAC,KAAK,CAAE,IAAM,EAAc,OAAS,EAAC,EAC9C,CACR,CACF,CACF"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { SimpleLogger } from "./shared.cjs";
|
|
2
|
+
import { Request, Response } from "express";
|
|
3
|
+
|
|
4
|
+
//#region src/health/readiness.d.ts
|
|
5
|
+
interface ReadinessDeps {
|
|
6
|
+
rabbit?: {
|
|
7
|
+
isConnected: () => Promise<boolean>;
|
|
8
|
+
};
|
|
9
|
+
sequelize?: {
|
|
10
|
+
authenticate: () => Promise<void>;
|
|
11
|
+
};
|
|
12
|
+
redis?: {
|
|
13
|
+
ping: () => Promise<void>;
|
|
14
|
+
};
|
|
15
|
+
elasticsearch?: {
|
|
16
|
+
ping: () => Promise<boolean>;
|
|
17
|
+
};
|
|
18
|
+
timeoutMs?: number;
|
|
19
|
+
logger?: SimpleLogger;
|
|
20
|
+
}
|
|
21
|
+
declare function readinessEndpoint(deps: ReadinessDeps): (_req: Request, res: Response) => Promise<boolean>;
|
|
22
|
+
//#endregion
|
|
23
|
+
export { readinessEndpoint };
|
|
24
|
+
//# sourceMappingURL=readiness.d.cts.map
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { SimpleLogger } from "./shared.js";
|
|
2
|
+
import { Request, Response } from "express";
|
|
3
|
+
|
|
4
|
+
//#region src/health/readiness.d.ts
|
|
5
|
+
interface ReadinessDeps {
|
|
6
|
+
rabbit?: {
|
|
7
|
+
isConnected: () => Promise<boolean>;
|
|
8
|
+
};
|
|
9
|
+
sequelize?: {
|
|
10
|
+
authenticate: () => Promise<void>;
|
|
11
|
+
};
|
|
12
|
+
redis?: {
|
|
13
|
+
ping: () => Promise<void>;
|
|
14
|
+
};
|
|
15
|
+
elasticsearch?: {
|
|
16
|
+
ping: () => Promise<boolean>;
|
|
17
|
+
};
|
|
18
|
+
timeoutMs?: number;
|
|
19
|
+
logger?: SimpleLogger;
|
|
20
|
+
}
|
|
21
|
+
declare function readinessEndpoint(deps: ReadinessDeps): (_req: Request, res: Response) => Promise<boolean>;
|
|
22
|
+
//#endregion
|
|
23
|
+
export { readinessEndpoint };
|
|
24
|
+
//# sourceMappingURL=readiness.d.ts.map
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{logger as e}from"../logger.js";import{eventLoopHeartbeat as t,runParallelChecks as n}from"./shared.js";function r(r){let{rabbit:i,sequelize:a,redis:o,elasticsearch:s,timeoutMs:c=400,logger:l=e}=r;return async(e,r)=>{try{await t();let e=[];return i&&e.push(i.isConnected().then(e=>e||Promise.reject(Error(`Rabbit`)))),a&&e.push(a.authenticate()),o&&e.push(o.ping()),s&&e.push(s.ping()),await n(e,c),r.json({status:`ready`}),!0}catch(e){return l.warn?.(`Readiness failed`,{err:e}),r.status(503).json({err:e.message}),!1}}}export{r as readinessEndpoint};
|
|
2
|
+
//# sourceMappingURL=readiness.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"readiness.js","names":["deps: ReadinessDeps","fallbackLogger","_req: Request","res: Response","checks: Promise<unknown>[]"],"sources":["../../src/health/readiness.ts"],"sourcesContent":["import type { Request, Response } from 'express';\nimport { logger as fallbackLogger } from '../logger';\nimport {\n eventLoopHeartbeat,\n runParallelChecks,\n type SimpleLogger,\n} from './shared';\n\nexport interface ReadinessDeps {\n rabbit?: { isConnected: () => Promise<boolean>; };\n sequelize?: { authenticate: () => Promise<void>; };\n redis?: { ping: () => Promise<void>; };\n elasticsearch?: { ping: () => Promise<boolean>; };\n timeoutMs?: number;\n logger?: SimpleLogger;\n}\n\nexport function readinessEndpoint(deps: ReadinessDeps) {\n const {\n rabbit,\n sequelize,\n redis,\n elasticsearch,\n timeoutMs = 400,\n logger = fallbackLogger,\n } = deps;\n\n return async (_req: Request, res: Response): Promise<boolean> => {\n try {\n await eventLoopHeartbeat();\n\n const checks: Promise<unknown>[] = [];\n if (rabbit) checks.push(rabbit.isConnected().then(ok => ok ? ok : Promise.reject(new Error('Rabbit'))));\n if (sequelize) checks.push(sequelize.authenticate());\n if (redis) checks.push(redis.ping());\n if (elasticsearch) checks.push(elasticsearch.ping());\n\n await runParallelChecks(checks, timeoutMs);\n res.json({ status: 'ready' });\n return true;\n } catch (err) {\n logger.warn?.('Readiness failed', { err });\n res.status(503).json({ err: (err as Error).message });\n return false;\n }\n };\n}\n"],"mappings":"8GAiBA,SAAgB,EAAkBA,EAAqB,CACrD,GAAM,CACJ,SACA,YACA,QACA,gBACA,YAAY,IACZ,OAAA,EAASC,EACV,CAAG,EAEJ,OAAO,MAAOC,EAAeC,IAAoC,CAC/D,GAAI,CACF,KAAM,IAAoB,CAE1B,IAAMC,EAA6B,CAAE,EAQrC,OAPI,GAAQ,EAAO,KAAK,EAAO,aAAa,CAAC,KAAK,GAAM,GAAU,QAAQ,OAAO,AAAI,MAAM,SAAA,CAAU,CAAC,CAAC,CACnG,GAAW,EAAO,KAAK,EAAU,cAAc,CAAC,CAChD,GAAO,EAAO,KAAK,EAAM,MAAM,CAAC,CAChC,GAAe,EAAO,KAAK,EAAc,MAAM,CAAC,CAEpD,KAAM,GAAkB,EAAQ,EAAU,CAC1C,EAAI,KAAK,CAAE,OAAQ,OAAS,EAAC,EACtB,CACR,OAAQ,EAAK,CAGZ,MAFA,GAAO,OAAO,mBAAoB,CAAE,KAAK,EAAC,CAC1C,EAAI,OAAO,IAAI,CAAC,KAAK,CAAE,IAAM,EAAc,OAAS,EAAC,EAC9C,CACR,CACF,CACF"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
function e(e=200){return new Promise((t,n)=>{let r=Date.now();setImmediate(()=>{Date.now()-r>e?n(Error(`event‑loop lag`)):t()})})}async function t(e,t){let n=new Promise((e,n)=>setTimeout(n,t,Error(`probe timeout`)));return Promise.race([Promise.all(e),n]).then(()=>void 0)}exports.eventLoopHeartbeat=e,exports.runParallelChecks=t;
|
|
2
|
+
//# sourceMappingURL=shared.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shared.cjs","names":["checks: Promise<unknown>[]","timeoutMs: number"],"sources":["../../src/health/shared.ts"],"sourcesContent":["export interface SimpleLogger {\n error: (message: string, meta: Record<string, unknown>) => void;\n warn?: (message: string, meta: Record<string, unknown>) => void;\n info?: (message: string, meta: Record<string, unknown>) => void;\n};\n\nexport function eventLoopHeartbeat(maxLag = 200): Promise<void> {\n return new Promise((resolve, reject) => {\n const start = Date.now();\n setImmediate(() => {\n if (Date.now() - start > maxLag) {\n reject(new Error('event‑loop lag'));\n } else {\n resolve();\n }\n });\n });\n}\n\nexport async function runParallelChecks(\n checks: Promise<unknown>[],\n timeoutMs: number,\n): Promise<void> {\n const timeout = new Promise((_, reject) =>\n setTimeout(reject, timeoutMs, new Error('probe timeout')),\n );\n return Promise.race([Promise.all(checks), timeout]).then(() => undefined);\n}\n"],"mappings":"AAMA,SAAgB,EAAmB,EAAS,IAAoB,CAC9D,OAAO,IAAI,QAAQ,CAAC,EAAS,IAAW,CACtC,IAAM,EAAQ,KAAK,KAAK,CACxB,aAAa,IAAM,CACjB,AAAI,KAAK,KAAK,CAAG,EAAQ,EACvB,EAAO,AAAI,MAAM,iBAAA,CAAkB,CAEnC,GAAS,AAEZ,EAAC,AACH,EACF,CAED,eAAsB,EACpBA,EACAC,EACe,CACf,IAAM,EAAU,IAAI,QAAQ,CAAC,EAAG,IAC9B,WAAW,EAAQ,EAAW,AAAI,MAAM,gBAAA,CAAiB,EAE3D,MAAO,SAAQ,KAAK,CAAC,QAAQ,IAAI,EAAO,CAAE,CAAQ,EAAC,CAAC,KAAK,QAAA,GAAgB,AAC1E"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
//#region src/health/shared.d.ts
|
|
2
|
+
interface SimpleLogger {
|
|
3
|
+
error: (message: string, meta: Record<string, unknown>) => void;
|
|
4
|
+
warn?: (message: string, meta: Record<string, unknown>) => void;
|
|
5
|
+
info?: (message: string, meta: Record<string, unknown>) => void;
|
|
6
|
+
}
|
|
7
|
+
//#endregion
|
|
8
|
+
export { SimpleLogger };
|
|
9
|
+
//# sourceMappingURL=shared.d.cts.map
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
//#region src/health/shared.d.ts
|
|
2
|
+
interface SimpleLogger {
|
|
3
|
+
error: (message: string, meta: Record<string, unknown>) => void;
|
|
4
|
+
warn?: (message: string, meta: Record<string, unknown>) => void;
|
|
5
|
+
info?: (message: string, meta: Record<string, unknown>) => void;
|
|
6
|
+
}
|
|
7
|
+
//#endregion
|
|
8
|
+
export { SimpleLogger };
|
|
9
|
+
//# sourceMappingURL=shared.d.ts.map
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
function e(e=200){return new Promise((t,n)=>{let r=Date.now();setImmediate(()=>{Date.now()-r>e?n(Error(`event‑loop lag`)):t()})})}async function t(e,t){let n=new Promise((e,n)=>setTimeout(n,t,Error(`probe timeout`)));return Promise.race([Promise.all(e),n]).then(()=>void 0)}export{e as eventLoopHeartbeat,t as runParallelChecks};
|
|
2
|
+
//# sourceMappingURL=shared.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shared.js","names":["checks: Promise<unknown>[]","timeoutMs: number"],"sources":["../../src/health/shared.ts"],"sourcesContent":["export interface SimpleLogger {\n error: (message: string, meta: Record<string, unknown>) => void;\n warn?: (message: string, meta: Record<string, unknown>) => void;\n info?: (message: string, meta: Record<string, unknown>) => void;\n};\n\nexport function eventLoopHeartbeat(maxLag = 200): Promise<void> {\n return new Promise((resolve, reject) => {\n const start = Date.now();\n setImmediate(() => {\n if (Date.now() - start > maxLag) {\n reject(new Error('event‑loop lag'));\n } else {\n resolve();\n }\n });\n });\n}\n\nexport async function runParallelChecks(\n checks: Promise<unknown>[],\n timeoutMs: number,\n): Promise<void> {\n const timeout = new Promise((_, reject) =>\n setTimeout(reject, timeoutMs, new Error('probe timeout')),\n );\n return Promise.race([Promise.all(checks), timeout]).then(() => undefined);\n}\n"],"mappings":"AAMA,SAAgB,EAAmB,EAAS,IAAoB,CAC9D,OAAO,IAAI,QAAQ,CAAC,EAAS,IAAW,CACtC,IAAM,EAAQ,KAAK,KAAK,CACxB,aAAa,IAAM,CACjB,AAAI,KAAK,KAAK,CAAG,EAAQ,EACvB,EAAO,AAAI,MAAM,iBAAA,CAAkB,CAEnC,GAAS,AAEZ,EAAC,AACH,EACF,CAED,eAAsB,EACpBA,EACAC,EACe,CACf,IAAM,EAAU,IAAI,QAAQ,CAAC,EAAG,IAC9B,WAAW,EAAQ,EAAW,AAAI,MAAM,gBAAA,CAAiB,EAE3D,MAAO,SAAQ,KAAK,CAAC,QAAQ,IAAI,EAAO,CAAE,CAAQ,EAAC,CAAC,KAAK,QAAA,GAAgB,AAC1E"}
|
package/lib/index.cjs
CHANGED
|
@@ -1 +1,2 @@
|
|
|
1
|
-
const e=require(`./alive-endpoint/middleware.cjs`),t=require(`./health
|
|
1
|
+
const e=require(`./alive-endpoint/middleware.cjs`),t=require(`./health/liveness.cjs`),n=require(`./health/readiness.cjs`),r={liveness:t.livenessEndpoint,readiness:n.readinessEndpoint};exports.aliveEndpoint=e.aliveEndpointMiddleware,exports.probes=r;
|
|
2
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["probes: { liveness: typeof livenessEndpoint; readiness: typeof readinessEndpoint; }","livenessEndpoint","readinessEndpoint"],"sources":["../src/index.ts"],"sourcesContent":["import { aliveEndpointMiddleware as aliveEndpoint } from './alive-endpoint/middleware';\nimport { livenessEndpoint } from './health/liveness';\nimport { readinessEndpoint } from './health/readiness';\n\nexport const probes: { liveness: typeof livenessEndpoint; readiness: typeof readinessEndpoint; } = {\n liveness: livenessEndpoint,\n readiness: readinessEndpoint,\n};\n\nexport { aliveEndpoint };\n"],"mappings":"0HAIaA,EAAsF,CACjG,SAAUC,EAAAA,iBACV,UAAWC,EAAAA,iBACZ"}
|
package/lib/index.d.cts
CHANGED
|
@@ -1,4 +1,12 @@
|
|
|
1
1
|
import { aliveEndpointMiddleware } from "./alive-endpoint/middleware.cjs";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
|
|
2
|
+
import { livenessEndpoint } from "./health/liveness.cjs";
|
|
3
|
+
import { readinessEndpoint } from "./health/readiness.cjs";
|
|
4
|
+
|
|
5
|
+
//#region src/index.d.ts
|
|
6
|
+
declare const probes: {
|
|
7
|
+
liveness: typeof livenessEndpoint;
|
|
8
|
+
readiness: typeof readinessEndpoint;
|
|
9
|
+
};
|
|
10
|
+
//#endregion
|
|
11
|
+
export { aliveEndpointMiddleware as aliveEndpoint, probes };
|
|
12
|
+
//# sourceMappingURL=index.d.cts.map
|
package/lib/index.d.ts
CHANGED
|
@@ -1,4 +1,12 @@
|
|
|
1
1
|
import { aliveEndpointMiddleware } from "./alive-endpoint/middleware.js";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
|
|
2
|
+
import { livenessEndpoint } from "./health/liveness.js";
|
|
3
|
+
import { readinessEndpoint } from "./health/readiness.js";
|
|
4
|
+
|
|
5
|
+
//#region src/index.d.ts
|
|
6
|
+
declare const probes: {
|
|
7
|
+
liveness: typeof livenessEndpoint;
|
|
8
|
+
readiness: typeof readinessEndpoint;
|
|
9
|
+
};
|
|
10
|
+
//#endregion
|
|
11
|
+
export { aliveEndpointMiddleware as aliveEndpoint, probes };
|
|
12
|
+
//# sourceMappingURL=index.d.ts.map
|
package/lib/index.js
CHANGED
|
@@ -1 +1,2 @@
|
|
|
1
|
-
import{aliveEndpointMiddleware as e}from"./alive-endpoint/middleware.js";import{
|
|
1
|
+
import{aliveEndpointMiddleware as e}from"./alive-endpoint/middleware.js";import{livenessEndpoint as t}from"./health/liveness.js";import{readinessEndpoint as n}from"./health/readiness.js";const r={liveness:t,readiness:n};export{e as aliveEndpoint,r as probes};
|
|
2
|
+
//# sourceMappingURL=index.js.map
|
package/lib/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":["probes: { liveness: typeof livenessEndpoint; readiness: typeof readinessEndpoint; }"],"sources":["../src/index.ts"],"sourcesContent":["import { aliveEndpointMiddleware as aliveEndpoint } from './alive-endpoint/middleware';\nimport { livenessEndpoint } from './health/liveness';\nimport { readinessEndpoint } from './health/readiness';\n\nexport const probes: { liveness: typeof livenessEndpoint; readiness: typeof readinessEndpoint; } = {\n liveness: livenessEndpoint,\n readiness: readinessEndpoint,\n};\n\nexport { aliveEndpoint };\n"],"mappings":"2LAIA,MAAaA,EAAsF,CACjG,SAAU,EACV,UAAW,CACZ"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import Pino from "pino";
|
|
2
|
+
|
|
3
|
+
//#region ../logger/src/index.d.ts
|
|
4
|
+
declare enum LogLevel {
|
|
5
|
+
trace = "trace",
|
|
6
|
+
debug = "debug",
|
|
7
|
+
info = "info",
|
|
8
|
+
warn = "warn",
|
|
9
|
+
error = "error",
|
|
10
|
+
fatal = "fatal",
|
|
11
|
+
}
|
|
12
|
+
type MiddlewareFunction = () => Record<string, unknown>;
|
|
13
|
+
declare class LoggerInstanceManager {
|
|
14
|
+
#private;
|
|
15
|
+
constructor(logLevel?: LogLevel);
|
|
16
|
+
// To support winston like logging in pino
|
|
17
|
+
private winstonLikeLoggerCall;
|
|
18
|
+
private addMetadata;
|
|
19
|
+
addContextMiddleware: (middleware: MiddlewareFunction) => number;
|
|
20
|
+
trace: (message: string, meta?: unknown) => void;
|
|
21
|
+
debug: (message: string, meta?: unknown) => void;
|
|
22
|
+
info: (message: string, meta?: unknown) => void;
|
|
23
|
+
warn: (message: string, meta?: unknown) => void;
|
|
24
|
+
error: (message: string, meta?: unknown) => void;
|
|
25
|
+
fatal: (message: string, meta?: unknown) => void;
|
|
26
|
+
child: (metadata: Record<string, unknown>) => Pino.Logger;
|
|
27
|
+
get level(): Pino.LevelWithSilentOrString;
|
|
28
|
+
}
|
|
29
|
+
//#endregion
|
|
30
|
+
export { LoggerInstanceManager };
|
|
31
|
+
//# sourceMappingURL=index.d.cts.map
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import Pino from "pino";
|
|
2
|
+
|
|
3
|
+
//#region ../logger/src/index.d.ts
|
|
4
|
+
declare enum LogLevel {
|
|
5
|
+
trace = "trace",
|
|
6
|
+
debug = "debug",
|
|
7
|
+
info = "info",
|
|
8
|
+
warn = "warn",
|
|
9
|
+
error = "error",
|
|
10
|
+
fatal = "fatal",
|
|
11
|
+
}
|
|
12
|
+
type MiddlewareFunction = () => Record<string, unknown>;
|
|
13
|
+
declare class LoggerInstanceManager {
|
|
14
|
+
#private;
|
|
15
|
+
constructor(logLevel?: LogLevel);
|
|
16
|
+
// To support winston like logging in pino
|
|
17
|
+
private winstonLikeLoggerCall;
|
|
18
|
+
private addMetadata;
|
|
19
|
+
addContextMiddleware: (middleware: MiddlewareFunction) => number;
|
|
20
|
+
trace: (message: string, meta?: unknown) => void;
|
|
21
|
+
debug: (message: string, meta?: unknown) => void;
|
|
22
|
+
info: (message: string, meta?: unknown) => void;
|
|
23
|
+
warn: (message: string, meta?: unknown) => void;
|
|
24
|
+
error: (message: string, meta?: unknown) => void;
|
|
25
|
+
fatal: (message: string, meta?: unknown) => void;
|
|
26
|
+
child: (metadata: Record<string, unknown>) => Pino.Logger;
|
|
27
|
+
get level(): Pino.LevelWithSilentOrString;
|
|
28
|
+
}
|
|
29
|
+
//#endregion
|
|
30
|
+
export { LoggerInstanceManager };
|
|
31
|
+
//# sourceMappingURL=index.d.ts.map
|
package/lib/logger.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const e=require(`./_virtual/rolldown_runtime.cjs`)
|
|
1
|
+
const e=require(`./_virtual/rolldown_runtime.cjs`),t=e.__toESM(require(`@autofleet/logger`)),n=(0,t.default)();exports.logger=n;
|
|
2
2
|
//# sourceMappingURL=logger.cjs.map
|
package/lib/logger.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logger.cjs","names":["logger: LoggerInstanceManager"],"sources":["../src/logger.ts"],"sourcesContent":["import Logger, { type LoggerInstanceManager } from '@autofleet/logger';\n\nexport const logger: LoggerInstanceManager = Logger();\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"logger.cjs","names":["logger: LoggerInstanceManager"],"sources":["../src/logger.ts"],"sourcesContent":["import Logger, { type LoggerInstanceManager } from '@autofleet/logger';\n\nexport const logger: LoggerInstanceManager = Logger();\n"],"mappings":"6FAEaA,EAAgC,CAAA,EAAA,EAAA,UAAQ"}
|
package/lib/logger.d.cts
CHANGED
package/lib/logger.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@autofleet/nitur",
|
|
3
|
-
"version": "2.2.
|
|
3
|
+
"version": "2.2.1-1",
|
|
4
4
|
"description": "A package for service monitoring",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./lib/index.js",
|
|
@@ -28,6 +28,12 @@
|
|
|
28
28
|
}
|
|
29
29
|
}
|
|
30
30
|
},
|
|
31
|
+
"scripts": {
|
|
32
|
+
"build": "tsdown",
|
|
33
|
+
"prepublish": "npm run build",
|
|
34
|
+
"test": "vitest",
|
|
35
|
+
"coverage": "vitest --coverage"
|
|
36
|
+
},
|
|
31
37
|
"repository": {
|
|
32
38
|
"type": "git",
|
|
33
39
|
"url": "git+https://github.com/Autofleet/autorepo.git"
|
|
@@ -39,22 +45,17 @@
|
|
|
39
45
|
},
|
|
40
46
|
"devDependencies": {
|
|
41
47
|
"@types/express": "^4.17.21",
|
|
42
|
-
"@types/node": "^18"
|
|
48
|
+
"@types/node": "^18",
|
|
49
|
+
"typescript": "^5.5.2"
|
|
43
50
|
},
|
|
44
51
|
"homepage": "https://github.com/Autofleet/autorepo/tree/master/packages/nitur#readme",
|
|
45
52
|
"files": [
|
|
46
53
|
"lib/**/*"
|
|
47
54
|
],
|
|
48
55
|
"dependencies": {
|
|
49
|
-
"
|
|
50
|
-
"@autofleet/logger": "^4.2.36"
|
|
56
|
+
"@autofleet/logger": "^4.1.0"
|
|
51
57
|
},
|
|
52
58
|
"engines": {
|
|
53
59
|
"node": "^18 || ^20 || >=22.0.0"
|
|
54
|
-
},
|
|
55
|
-
"scripts": {
|
|
56
|
-
"build": "tsdown",
|
|
57
|
-
"test": "vitest",
|
|
58
|
-
"coverage": "vitest --coverage"
|
|
59
60
|
}
|
|
60
|
-
}
|
|
61
|
+
}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
const e=require(`./types.cjs`),t={[e.CLIENT_TYPES.REDIS]:async({client:e,name:t,logger:n})=>{try{await e.ping()}catch(e){throw n.error(`Redis ping error for '${t}': ${e instanceof Error?e.message:String(e)}`),e}},[e.CLIENT_TYPES.SEQUELIZE]:async({client:e,name:t,logger:n})=>{try{let[[t]]=await e.query(`SELECT 1 as status`);if(t?.status!==1)throw Error(`Unexpected query result`)}catch(e){throw n.error(`Sequelize health check error for '${t}': ${e instanceof Error?e.message:String(e)}`),e}},[e.CLIENT_TYPES.ELASTIC_SEARCH]:async({client:e,name:t,logger:n})=>{try{if(!await e.ping())throw Error(`Elasticsearch ping returned false`)}catch(e){throw n.error(`Elasticsearch health check error for '${t}': ${e instanceof Error?e.message:String(e)}`),e}},[e.CLIENT_TYPES.RABBIT]:async({client:e,name:t,logger:n})=>{try{if(!await e.isConnected())throw Error(`RabbitMQ is not connected`)}catch(e){throw n.error(`RabbitMQ health check error for '${t}': ${e instanceof Error?e.message:String(e)}`),e}}};exports.DEFAULT_CLIENT_HEALTHCHECK_FUNC_MAP=t;
|
|
2
|
-
//# sourceMappingURL=health-check-handlers.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"health-check-handlers.cjs","names":["DEFAULT_CLIENT_HEALTHCHECK_FUNC_MAP: Partial<Record<ClientType, (options: { client: any; name: string; logger: LoggerInstanceManager; }) => any>>","CLIENT_TYPES"],"sources":["../../src/health-manager/health-check-handlers.ts"],"sourcesContent":["import type {\n RedisClient,\n SequelizeClient,\n ElasticsearchClient,\n RabbitMQClient,\n ClientType,\n} from './types';\nimport type { LoggerInstanceManager } from '@autofleet/logger';\nimport { CLIENT_TYPES } from './types';\n\nexport const DEFAULT_CLIENT_HEALTHCHECK_FUNC_MAP: Partial<Record<ClientType, (options: { client: any; name: string; logger: LoggerInstanceManager; }) => any>> = {\n [CLIENT_TYPES.REDIS]: async ({ client, name, logger }: { client: RedisClient; name: string; logger: LoggerInstanceManager; }) => {\n try {\n await client.ping();\n } catch (error) {\n logger.error(`Redis ping error for '${name}': ${error instanceof Error ? error.message : String(error)}`);\n throw error;\n }\n },\n [CLIENT_TYPES.SEQUELIZE]: async ({ client, name, logger }: { client: SequelizeClient; name: string; logger: LoggerInstanceManager; }) => {\n try {\n const [[result]] = await client.query('SELECT 1 as status');\n if (result?.status !== 1) {\n throw new Error('Unexpected query result');\n }\n } catch (error) {\n logger.error(`Sequelize health check error for '${name}': ${error instanceof Error ? error.message : String(error)}`);\n throw error;\n }\n },\n [CLIENT_TYPES.ELASTIC_SEARCH]: async ({ client, name, logger }: { client: ElasticsearchClient; name: string; logger: LoggerInstanceManager; }) => {\n try {\n const isAlive = await client.ping();\n if (!isAlive) {\n throw new Error('Elasticsearch ping returned false');\n }\n } catch (error) {\n logger.error(`Elasticsearch health check error for '${name}': ${error instanceof Error ? error.message : String(error)}`);\n throw error;\n }\n },\n [CLIENT_TYPES.RABBIT]: async ({ client, name, logger }: { client: RabbitMQClient; name: string; logger: LoggerInstanceManager; }) => {\n try {\n const isConnected = await client.isConnected();\n if (!isConnected) {\n throw new Error('RabbitMQ is not connected');\n }\n } catch (error) {\n logger.error(`RabbitMQ health check error for '${name}': ${error instanceof Error ? error.message : String(error)}`);\n throw error;\n }\n },\n};\n"],"mappings":"+BAUaA,EAAoJ,EAC9JC,EAAAA,aAAa,OAAQ,MAAO,CAAE,SAAQ,OAAM,YAAoF,CAC/H,GAAI,CACF,MAAM,EAAO,MAAM,OACZ,EAAO,CAEd,MADA,EAAO,MAAM,yBAAyB,EAAK,KAAK,aAAiB,MAAQ,EAAM,QAAU,OAAO,EAAM,GAAG,CACnG,KAGTA,EAAAA,aAAa,WAAY,MAAO,CAAE,SAAQ,OAAM,YAAwF,CACvI,GAAI,CACF,GAAM,CAAC,CAAC,IAAW,MAAM,EAAO,MAAM,qBAAqB,CAC3D,GAAI,GAAQ,SAAW,EACrB,MAAU,MAAM,0BAA0B,OAErC,EAAO,CAEd,MADA,EAAO,MAAM,qCAAqC,EAAK,KAAK,aAAiB,MAAQ,EAAM,QAAU,OAAO,EAAM,GAAG,CAC/G,KAGTA,EAAAA,aAAa,gBAAiB,MAAO,CAAE,SAAQ,OAAM,YAA4F,CAChJ,GAAI,CAEF,GAAI,CADY,MAAM,EAAO,MAAM,CAEjC,MAAU,MAAM,oCAAoC,OAE/C,EAAO,CAEd,MADA,EAAO,MAAM,yCAAyC,EAAK,KAAK,aAAiB,MAAQ,EAAM,QAAU,OAAO,EAAM,GAAG,CACnH,KAGTA,EAAAA,aAAa,QAAS,MAAO,CAAE,SAAQ,OAAM,YAAuF,CACnI,GAAI,CAEF,GAAI,CADgB,MAAM,EAAO,aAAa,CAE5C,MAAU,MAAM,4BAA4B,OAEvC,EAAO,CAEd,MADA,EAAO,MAAM,oCAAoC,EAAK,KAAK,aAAiB,MAAQ,EAAM,QAAU,OAAO,EAAM,GAAG,CAC9G,IAGX"}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{CLIENT_TYPES as e}from"./types.js";const t={[e.REDIS]:async({client:e,name:t,logger:n})=>{try{await e.ping()}catch(e){throw n.error(`Redis ping error for '${t}': ${e instanceof Error?e.message:String(e)}`),e}},[e.SEQUELIZE]:async({client:e,name:t,logger:n})=>{try{let[[t]]=await e.query(`SELECT 1 as status`);if(t?.status!==1)throw Error(`Unexpected query result`)}catch(e){throw n.error(`Sequelize health check error for '${t}': ${e instanceof Error?e.message:String(e)}`),e}},[e.ELASTIC_SEARCH]:async({client:e,name:t,logger:n})=>{try{if(!await e.ping())throw Error(`Elasticsearch ping returned false`)}catch(e){throw n.error(`Elasticsearch health check error for '${t}': ${e instanceof Error?e.message:String(e)}`),e}},[e.RABBIT]:async({client:e,name:t,logger:n})=>{try{if(!await e.isConnected())throw Error(`RabbitMQ is not connected`)}catch(e){throw n.error(`RabbitMQ health check error for '${t}': ${e instanceof Error?e.message:String(e)}`),e}}};export{t as DEFAULT_CLIENT_HEALTHCHECK_FUNC_MAP};
|
|
2
|
-
//# sourceMappingURL=health-check-handlers.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"health-check-handlers.js","names":["DEFAULT_CLIENT_HEALTHCHECK_FUNC_MAP: Partial<Record<ClientType, (options: { client: any; name: string; logger: LoggerInstanceManager; }) => any>>"],"sources":["../../src/health-manager/health-check-handlers.ts"],"sourcesContent":["import type {\n RedisClient,\n SequelizeClient,\n ElasticsearchClient,\n RabbitMQClient,\n ClientType,\n} from './types';\nimport type { LoggerInstanceManager } from '@autofleet/logger';\nimport { CLIENT_TYPES } from './types';\n\nexport const DEFAULT_CLIENT_HEALTHCHECK_FUNC_MAP: Partial<Record<ClientType, (options: { client: any; name: string; logger: LoggerInstanceManager; }) => any>> = {\n [CLIENT_TYPES.REDIS]: async ({ client, name, logger }: { client: RedisClient; name: string; logger: LoggerInstanceManager; }) => {\n try {\n await client.ping();\n } catch (error) {\n logger.error(`Redis ping error for '${name}': ${error instanceof Error ? error.message : String(error)}`);\n throw error;\n }\n },\n [CLIENT_TYPES.SEQUELIZE]: async ({ client, name, logger }: { client: SequelizeClient; name: string; logger: LoggerInstanceManager; }) => {\n try {\n const [[result]] = await client.query('SELECT 1 as status');\n if (result?.status !== 1) {\n throw new Error('Unexpected query result');\n }\n } catch (error) {\n logger.error(`Sequelize health check error for '${name}': ${error instanceof Error ? error.message : String(error)}`);\n throw error;\n }\n },\n [CLIENT_TYPES.ELASTIC_SEARCH]: async ({ client, name, logger }: { client: ElasticsearchClient; name: string; logger: LoggerInstanceManager; }) => {\n try {\n const isAlive = await client.ping();\n if (!isAlive) {\n throw new Error('Elasticsearch ping returned false');\n }\n } catch (error) {\n logger.error(`Elasticsearch health check error for '${name}': ${error instanceof Error ? error.message : String(error)}`);\n throw error;\n }\n },\n [CLIENT_TYPES.RABBIT]: async ({ client, name, logger }: { client: RabbitMQClient; name: string; logger: LoggerInstanceManager; }) => {\n try {\n const isConnected = await client.isConnected();\n if (!isConnected) {\n throw new Error('RabbitMQ is not connected');\n }\n } catch (error) {\n logger.error(`RabbitMQ health check error for '${name}': ${error instanceof Error ? error.message : String(error)}`);\n throw error;\n }\n },\n};\n"],"mappings":"0CAUA,MAAaA,EAAoJ,EAC9J,EAAa,OAAQ,MAAO,CAAE,SAAQ,OAAM,YAAoF,CAC/H,GAAI,CACF,MAAM,EAAO,MAAM,OACZ,EAAO,CAEd,MADA,EAAO,MAAM,yBAAyB,EAAK,KAAK,aAAiB,MAAQ,EAAM,QAAU,OAAO,EAAM,GAAG,CACnG,KAGT,EAAa,WAAY,MAAO,CAAE,SAAQ,OAAM,YAAwF,CACvI,GAAI,CACF,GAAM,CAAC,CAAC,IAAW,MAAM,EAAO,MAAM,qBAAqB,CAC3D,GAAI,GAAQ,SAAW,EACrB,MAAU,MAAM,0BAA0B,OAErC,EAAO,CAEd,MADA,EAAO,MAAM,qCAAqC,EAAK,KAAK,aAAiB,MAAQ,EAAM,QAAU,OAAO,EAAM,GAAG,CAC/G,KAGT,EAAa,gBAAiB,MAAO,CAAE,SAAQ,OAAM,YAA4F,CAChJ,GAAI,CAEF,GAAI,CADY,MAAM,EAAO,MAAM,CAEjC,MAAU,MAAM,oCAAoC,OAE/C,EAAO,CAEd,MADA,EAAO,MAAM,yCAAyC,EAAK,KAAK,aAAiB,MAAQ,EAAM,QAAU,OAAO,EAAM,GAAG,CACnH,KAGT,EAAa,QAAS,MAAO,CAAE,SAAQ,OAAM,YAAuF,CACnI,GAAI,CAEF,GAAI,CADgB,MAAM,EAAO,aAAa,CAE5C,MAAU,MAAM,4BAA4B,OAEvC,EAAO,CAEd,MADA,EAAO,MAAM,oCAAoC,EAAK,KAAK,aAAiB,MAAQ,EAAM,QAAU,OAAO,EAAM,GAAG,CAC9G,IAGX"}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
const e=require(`../_virtual/rolldown_runtime.cjs`),t=require(`./health-check-handlers.cjs`),n=require(`./shutdown-handlers.cjs`);let r=require(`node:timers/promises`),i=require(`@autofleet/errors`);var a=class{constructor(e){this.DEFAULT_CLIENT_OPTIONS={includeInLivenessCheck:!0,includeInReadinessCheck:!0},this.DEFAULT_SERVER_OPTIONS={runDefaultShutdownHandler:!0,name:`server`},this.DEFAULT_CONFIG={shutdownDelayMs:5e3,useExit0:!0,shouldSetupSignalHandlers:!0,enableLivenessOptimization:!0},this.isShuttingDown=!1,this.isReady=!1,this.clientsMap=new Map,this.livenessChecks=[],this.readinessChecks=[],this.canSafelySkipLivenessWhenReady=(e,t)=>!(e&&!t),this.config={...this.DEFAULT_CONFIG,...e.config??{}},this.logger=e.logger,e.server&&this.attachServer(e.server),this.storeClientsWithDefaults(e),this.initializeHealthChecks(),this.config.shouldSetupSignalHandlers&&this.setupSignalHandlers()}storeClientsWithDefaults(e){let r=e.clients;r&&Object.entries(r).forEach(([e,r])=>{if(!r)return;let i=(Array.isArray(r)?r:[r]).map(r=>{let i={...this.DEFAULT_CLIENT_OPTIONS,name:e,...r.options},a=t.DEFAULT_CLIENT_HEALTHCHECK_FUNC_MAP[e],o;r.healthCheck?o=r.healthCheck:a?o=e=>a({client:e.client,name:e.name,logger:this.logger}):(this.logger.warn(`No health check provided for client type '${e}' and no default implementation exists`),o=void 0);let s=n.DEFAULT_CLIENT_SHUTDOWN_HANDLERS_MAP[e],c;return r.shutdown?c=r.shutdown:s?c=e=>s({client:e.client,signal:e.signal,name:e.name,logger:this.logger}):(this.logger.warn(`No shutdown handler provided for client type '${e}' and no default implementation exists`),c=void 0),{connection:r.connection,healthCheck:o,shutdown:c,options:i}});this.clientsMap.set(e,i)})}setupSignalHandlers(){this.logger.info(`Setting up global signal listeners for graceful shutdown`),process.on(`SIGTERM`,async()=>{await this.shutdown(`SIGTERM`)}),process.on(`SIGINT`,async()=>{await this.shutdown(`SIGINT`)})}initializeHealthChecks(){let e=!0;this.clientsMap.forEach(t=>{t.forEach(t=>{if(!t.healthCheck)return;let n=t.options?.includeInLivenessCheck??!0,r=t.options?.includeInReadinessCheck??!0;this.canSafelySkipLivenessWhenReady(n,r)||(e=!1),n&&this.livenessChecks.push({check:t.healthCheck,client:t.connection,name:t.options?.name||`unknown`,customHandlersPayload:t.options?.customHandlersPayload}),r&&this.readinessChecks.push({check:t.healthCheck,client:t.connection,name:t.options?.name||`unknown`,customHandlersPayload:t.options?.customHandlersPayload})})}),this.config.enableLivenessOptimization=this.config.enableLivenessOptimization&&e,this.config.enableLivenessOptimization?this.logger.info(`Liveness check optimization enabled - liveness checks will be skipped when pod is ready`):e||this.logger.warn(`Liveness check optimization disabled - some clients are in liveness checks but not in readiness checks`)}attachServer(e){this.server={server:e.server,shutdown:e.shutdown??(async()=>n.defaultServerShutdownHandler(e.server,this.logger)),options:{...this.DEFAULT_SERVER_OPTIONS,...e.options??{}}}}async aliveCheck(){if(this.isShuttingDown||this.config.enableLivenessOptimization&&this.isReady)return{statusCode:200,status:`ok`};try{return await Promise.all(this.livenessChecks.map(({check:e,client:t,name:n,customHandlersPayload:r})=>e({client:t,name:n,customHandlersPayload:r}))),{statusCode:200,status:`ok`}}catch(e){let t=new i.ServiceUnavailableError(`Liveness probe failed: ${e.message}`);throw t.stack=e.stack,t}}async readyCheck(){if(this.isShuttingDown)throw this.isReady=!1,new i.ServiceUnavailableError(`Readiness probe failed: Application is shutting down`);try{return await Promise.all(this.readinessChecks.map(({check:e,client:t,name:n,customHandlersPayload:r})=>e({client:t,name:n,customHandlersPayload:r}))),this.isReady=!0,{statusCode:200,status:`ok`}}catch(e){this.isReady=!1;let t=new i.ServiceUnavailableError(`Readiness probe failed: ${e.message}`);throw t.stack=e.stack,t}}async shutdown(e=`MANUAL`){try{if(this.isShuttingDown){this.logger.warn(`Shutdown already in progress`);return}let{shutdownDelayMs:t,useExit0:n,onShutdown:i,beforeShutdown:a}=this.config;this.isShuttingDown=!0,this.isReady=!1,this.logger.info(`${e} received: setting readiness state to false`),await a?.(),this.logger.info(`Waiting ${t}ms before shutdown...`),await(0,r.setTimeout)(t);let o=[];this.clientsMap.forEach(e=>{e.forEach(e=>{e.shutdown&&o.push(e.options?.name||`unknown`)})}),this.logger.info(`Executing shutdown hooks...`,{clients:o});let s=[];this.clientsMap.forEach(t=>{t.forEach(t=>{t.shutdown&&s.push(t.shutdown({signal:e,client:t.connection,name:t.options?.name||`unknown`,customHandlersPayload:t.options?.customHandlersPayload}))})}),await Promise.allSettled(s),await i?.(),this.server?.options?.runDefaultShutdownHandler&&(this.logger.info(`Shutting down server...`),await this.server?.shutdown?.()),this.logger.info(`Shutdown process completed`),n&&(this.logger.info(`Exiting process after ${e}`),process.exit(0))}catch(t){this.logger.error(`Error during shutdown process, forcing process exit despite shutdown error`,{error:t,signal:e}),process.exit(1)}}};exports.HealthManager=a;
|
|
2
|
-
//# sourceMappingURL=health-manager.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"health-manager.cjs","names":["client","DEFAULT_CLIENT_HEALTHCHECK_FUNC_MAP","healthCheck: ((options: { client: any; name: string; customHandlersPayload?: any; }) => Promise<void>) | undefined","options","DEFAULT_CLIENT_SHUTDOWN_HANDLERS_MAP","shutdown: ((options: { signal?: string; client: any; name: string; customHandlersPayload?: any; }) => Promise<void>) | undefined","defaultServerShutdownHandler","error: any","ServiceUnavailableError","clientNames: string[]","shutdownPromises: Promise<any>[]"],"sources":["../../src/health-manager/health-manager.ts"],"sourcesContent":["import { setTimeout } from 'node:timers/promises';\nimport { ServiceUnavailableError } from '@autofleet/errors';\nimport type {\n ClientConfig,\n HealthManagerConfig,\n HealthManagerOptions,\n ClientType,\n ServerConfig,\n} from './types';\nimport type { LoggerInstanceManager } from '@autofleet/logger';\nimport { DEFAULT_CLIENT_HEALTHCHECK_FUNC_MAP } from './health-check-handlers';\nimport { DEFAULT_CLIENT_SHUTDOWN_HANDLERS_MAP, defaultServerShutdownHandler } from './shutdown-handlers';\n\n/**\n * Manages application health state and graceful shutdown for Kubernetes liveness/readiness probes\n *\n * Features:\n * - Provides aliveCheck() and readyCheck() methods for liveness/readiness probes\n * - Auto-registers SIGTERM/SIGINT handlers for graceful shutdown\n * - Manages ready state during shutdown to fail readiness probes\n */\nexport class HealthManager {\n private readonly DEFAULT_CLIENT_OPTIONS = {\n includeInLivenessCheck: true,\n includeInReadinessCheck: true,\n };\n\n private readonly DEFAULT_SERVER_OPTIONS = {\n runDefaultShutdownHandler: true,\n name: 'server',\n };\n\n private readonly DEFAULT_CONFIG: HealthManagerConfig = {\n shutdownDelayMs: 5_000,\n useExit0: true,\n shouldSetupSignalHandlers: true,\n enableLivenessOptimization: true,\n };\n\n private isShuttingDown = false;\n private isReady = false;\n\n private config: HealthManagerConfig;\n\n private clientsMap = new Map<string, ClientConfig<any>[]>();\n private server: Required<ServerConfig> | undefined;\n\n private livenessChecks: { check: (options: { client: any; name: string; customHandlersPayload?: any; }) => Promise<void>; client: any; name: string; customHandlersPayload?: any; }[] = [];\n private readinessChecks: { check: (options: { client: any; name: string; customHandlersPayload?: any; }) => Promise<void>; client: any; name: string; customHandlersPayload?: any; }[] = [];\n\n private logger: LoggerInstanceManager;\n\n /**\n * Creates a new HealthManager instance\n *\n * @param params Configuration options for health checks and shutdown behavior\n */\n constructor(params: HealthManagerOptions) {\n this.config = {\n ...this.DEFAULT_CONFIG,\n ...(params.config ?? {}),\n };\n\n this.logger = params.logger;\n if (params.server) {\n this.attachServer(params.server);\n }\n\n this.storeClientsWithDefaults(params);\n\n this.initializeHealthChecks();\n\n if (this.config.shouldSetupSignalHandlers) {\n this.setupSignalHandlers();\n }\n }\n\n /**\n * Store clients with default health check and shutdown functions\n * @private\n */\n private storeClientsWithDefaults(params: HealthManagerOptions): void {\n const clients = params.clients;\n if (!clients) {\n return;\n }\n\n Object.entries(clients).forEach(([type, client]) => {\n if (!client) {\n return;\n }\n\n const clientsArray = Array.isArray(client) ? client : [client];\n\n // Apply default values to each client config\n const clientsWithDefaults = clientsArray.map((client) => {\n const options = {\n ...this.DEFAULT_CLIENT_OPTIONS,\n name: type,\n ...client.options,\n };\n\n const defaultHealthCheck = DEFAULT_CLIENT_HEALTHCHECK_FUNC_MAP[type as ClientType];\n let healthCheck: ((options: { client: any; name: string; customHandlersPayload?: any; }) => Promise<void>) | undefined;\n\n if (client.healthCheck) {\n healthCheck = client.healthCheck;\n } else if (defaultHealthCheck) {\n healthCheck = (options: { client: any; name: string; customHandlersPayload?: any; }) => defaultHealthCheck({ client: options.client, name: options.name, logger: this.logger });\n } else {\n this.logger.warn(`No health check provided for client type '${type}' and no default implementation exists`);\n healthCheck = undefined;\n }\n\n const defaultShutdown = DEFAULT_CLIENT_SHUTDOWN_HANDLERS_MAP[type as ClientType];\n let shutdown: ((options: { signal?: string; client: any; name: string; customHandlersPayload?: any; }) => Promise<void>) | undefined;\n\n if (client.shutdown) {\n shutdown = client.shutdown;\n } else if (defaultShutdown) {\n shutdown = (options: { signal?: string; client: any; name: string; customHandlersPayload?: any; }) => defaultShutdown(\n { client: options.client, signal: options.signal, name: options.name, logger: this.logger },\n );\n } else {\n this.logger.warn(`No shutdown handler provided for client type '${type}' and no default implementation exists`);\n shutdown = undefined;\n }\n\n return {\n connection: client.connection,\n healthCheck,\n shutdown,\n options,\n };\n });\n\n this.clientsMap.set(type, clientsWithDefaults);\n });\n }\n\n /**\n * Register SIGTERM and SIGINT signal listeners\n * @private\n */\n private setupSignalHandlers(): void {\n this.logger.info('Setting up global signal listeners for graceful shutdown');\n\n process.on('SIGTERM', async () => {\n await this.shutdown('SIGTERM');\n });\n\n process.on('SIGINT', async () => {\n await this.shutdown('SIGINT');\n });\n }\n\n /**\n * Check if liveness optimization is safe to enable for a given client configuration\n * If a client is in liveness but not readiness, we cannot skip liveness checks\n * because the optimization relies on readiness passing, but this client isn't checked in readiness\n * @private\n */\n private canSafelySkipLivenessWhenReady = (includeInLiveness: boolean, includeInReadiness: boolean): boolean =>\n !(includeInLiveness && !includeInReadiness);\n\n /**\n * Initialize health check arrays based on configured clients\n * @private\n */\n private initializeHealthChecks(): void {\n let allClientsAllowLivenessOptimization = true;\n\n this.clientsMap.forEach((clients) => {\n clients.forEach((client) => {\n if (!client.healthCheck) {\n return;\n }\n\n const includeInLiveness = client.options?.includeInLivenessCheck ?? true;\n const includeInReadiness = client.options?.includeInReadinessCheck ?? true;\n\n // Check if this client configuration allows liveness optimization\n if (!this.canSafelySkipLivenessWhenReady(includeInLiveness, includeInReadiness)) {\n allClientsAllowLivenessOptimization = false;\n }\n\n if (includeInLiveness) {\n this.livenessChecks.push({\n check: client.healthCheck,\n client: client.connection,\n name: client.options?.name || 'unknown',\n customHandlersPayload: client.options?.customHandlersPayload,\n });\n }\n\n if (includeInReadiness) {\n this.readinessChecks.push({\n check: client.healthCheck,\n client: client.connection,\n name: client.options?.name || 'unknown',\n customHandlersPayload: client.options?.customHandlersPayload,\n });\n }\n });\n });\n\n // Apply optimization setting: only enable if user requested it AND all clients allow it\n this.config.enableLivenessOptimization = this.config.enableLivenessOptimization && allClientsAllowLivenessOptimization;\n\n // Log optimization status\n if (this.config.enableLivenessOptimization) {\n this.logger.info('Liveness check optimization enabled - liveness checks will be skipped when pod is ready');\n } else if (!allClientsAllowLivenessOptimization) {\n this.logger.warn('Liveness check optimization disabled - some clients are in liveness checks but not in readiness checks');\n }\n }\n\n /**\n * Attach an HTTP or HTTPS server to be managed during shutdown\n * @param serverConfig Server configuration including the server instance and optional shutdown handler\n */\n attachServer(serverConfig: ServerConfig): void {\n this.server = {\n server: serverConfig.server,\n shutdown: serverConfig.shutdown ?? (async () => defaultServerShutdownHandler(serverConfig.server, this.logger)),\n options: {\n ...this.DEFAULT_SERVER_OPTIONS,\n ...(serverConfig.options ?? {}),\n },\n };\n }\n\n /**\n * Performs liveness health checks for clients configured with includeInLivenessCheck\n *\n * @returns Promise that resolves to { status: 'ok', statusCode: 200 } on success\n * @throws ServiceUnavailableError with statusCode 503 if any health check fails\n */\n async aliveCheck(): Promise<{ status: string; statusCode: number; }> {\n if (this.isShuttingDown) {\n return { statusCode: 200, status: 'ok' };\n }\n\n // Skip liveness check if optimization is enabled and pod is already ready\n if (this.config.enableLivenessOptimization && this.isReady) {\n return { statusCode: 200, status: 'ok' };\n }\n\n try {\n await Promise.all(\n this.livenessChecks.map(({ check, client, name, customHandlersPayload }) =>\n check({ client, name, customHandlersPayload }),\n ),\n );\n\n return { statusCode: 200, status: 'ok' };\n } catch (error: any) {\n const err = new ServiceUnavailableError(`Liveness probe failed: ${error.message}`);\n err.stack = error.stack;\n throw err;\n }\n }\n\n /**\n * Performs readiness health checks for clients configured with includeInReadinessCheck\n *\n * @returns Promise that resolves to { status: 'ok', statusCode: 200 } if ready\n * @throws ServiceUnavailableError with statusCode 503 if not ready or health check fails\n */\n async readyCheck(): Promise<{ status: string; statusCode: number; }> {\n if (this.isShuttingDown) {\n this.isReady = false;\n throw new ServiceUnavailableError('Readiness probe failed: Application is shutting down');\n }\n\n try {\n await Promise.all(\n this.readinessChecks.map(({ check, client, name, customHandlersPayload }) =>\n check({ client, name, customHandlersPayload }),\n ),\n );\n this.isReady = true;\n\n return { statusCode: 200, status: 'ok' };\n } catch (error: any) {\n this.isReady = false;\n const err = new ServiceUnavailableError(`Readiness probe failed: ${error.message}`);\n err.stack = error.stack;\n throw err;\n }\n }\n\n /**\n * Triggers graceful shutdown process\n * Can be called manually or automatically via SIGTERM/SIGINT signal handlers\n *\n * @param signal - Signal name (e.g., 'SIGTERM', 'SIGINT', 'MANUAL')\n */\n async shutdown(signal = 'MANUAL'): Promise<void> {\n try {\n if (this.isShuttingDown) {\n this.logger.warn('Shutdown already in progress');\n return;\n }\n\n const { shutdownDelayMs, useExit0, onShutdown, beforeShutdown } = this.config;\n\n this.isShuttingDown = true;\n this.isReady = false;\n\n this.logger.info(`${signal} received: setting readiness state to false`);\n\n await beforeShutdown?.();\n\n this.logger.info(`Waiting ${shutdownDelayMs}ms before shutdown...`);\n await setTimeout(shutdownDelayMs);\n\n // Collect client names that have shutdown handlers\n const clientNames: string[] = [];\n this.clientsMap.forEach((clients) => {\n clients.forEach((client) => {\n if (client.shutdown) {\n clientNames.push(client.options?.name || 'unknown');\n }\n });\n });\n\n this.logger.info('Executing shutdown hooks...', { clients: clientNames });\n\n const shutdownPromises: Promise<any>[] = [];\n this.clientsMap.forEach((clients) => {\n clients.forEach((client) => {\n if (client.shutdown) {\n shutdownPromises.push(client.shutdown({\n signal,\n client: client.connection,\n name: client.options?.name || 'unknown',\n customHandlersPayload: client.options?.customHandlersPayload,\n }));\n }\n });\n });\n\n await Promise.allSettled(shutdownPromises);\n\n await onShutdown?.();\n\n if (this.server?.options?.runDefaultShutdownHandler) {\n this.logger.info('Shutting down server...');\n await this.server?.shutdown?.();\n }\n\n this.logger.info('Shutdown process completed');\n\n if (useExit0) {\n this.logger.info(`Exiting process after ${signal}`);\n process.exit(0);\n }\n } catch (error: any) {\n this.logger.error('Error during shutdown process, forcing process exit despite shutdown error', { error, signal });\n process.exit(1);\n }\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
import { HealthManagerOptions, ServerConfig } from "./types.cjs";
|
|
2
|
-
|
|
3
|
-
//#region src/health-manager/health-manager.d.ts
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Manages application health state and graceful shutdown for Kubernetes liveness/readiness probes
|
|
7
|
-
*
|
|
8
|
-
* Features:
|
|
9
|
-
* - Provides aliveCheck() and readyCheck() methods for liveness/readiness probes
|
|
10
|
-
* - Auto-registers SIGTERM/SIGINT handlers for graceful shutdown
|
|
11
|
-
* - Manages ready state during shutdown to fail readiness probes
|
|
12
|
-
*/
|
|
13
|
-
declare class HealthManager {
|
|
14
|
-
private readonly DEFAULT_CLIENT_OPTIONS;
|
|
15
|
-
private readonly DEFAULT_SERVER_OPTIONS;
|
|
16
|
-
private readonly DEFAULT_CONFIG;
|
|
17
|
-
private isShuttingDown;
|
|
18
|
-
private isReady;
|
|
19
|
-
private config;
|
|
20
|
-
private clientsMap;
|
|
21
|
-
private server;
|
|
22
|
-
private livenessChecks;
|
|
23
|
-
private readinessChecks;
|
|
24
|
-
private logger;
|
|
25
|
-
/**
|
|
26
|
-
* Creates a new HealthManager instance
|
|
27
|
-
*
|
|
28
|
-
* @param params Configuration options for health checks and shutdown behavior
|
|
29
|
-
*/
|
|
30
|
-
constructor(params: HealthManagerOptions);
|
|
31
|
-
/**
|
|
32
|
-
* Store clients with default health check and shutdown functions
|
|
33
|
-
* @private
|
|
34
|
-
*/
|
|
35
|
-
private storeClientsWithDefaults;
|
|
36
|
-
/**
|
|
37
|
-
* Register SIGTERM and SIGINT signal listeners
|
|
38
|
-
* @private
|
|
39
|
-
*/
|
|
40
|
-
private setupSignalHandlers;
|
|
41
|
-
/**
|
|
42
|
-
* Check if liveness optimization is safe to enable for a given client configuration
|
|
43
|
-
* If a client is in liveness but not readiness, we cannot skip liveness checks
|
|
44
|
-
* because the optimization relies on readiness passing, but this client isn't checked in readiness
|
|
45
|
-
* @private
|
|
46
|
-
*/
|
|
47
|
-
private canSafelySkipLivenessWhenReady;
|
|
48
|
-
/**
|
|
49
|
-
* Initialize health check arrays based on configured clients
|
|
50
|
-
* @private
|
|
51
|
-
*/
|
|
52
|
-
private initializeHealthChecks;
|
|
53
|
-
/**
|
|
54
|
-
* Attach an HTTP or HTTPS server to be managed during shutdown
|
|
55
|
-
* @param serverConfig Server configuration including the server instance and optional shutdown handler
|
|
56
|
-
*/
|
|
57
|
-
attachServer(serverConfig: ServerConfig): void;
|
|
58
|
-
/**
|
|
59
|
-
* Performs liveness health checks for clients configured with includeInLivenessCheck
|
|
60
|
-
*
|
|
61
|
-
* @returns Promise that resolves to { status: 'ok', statusCode: 200 } on success
|
|
62
|
-
* @throws ServiceUnavailableError with statusCode 503 if any health check fails
|
|
63
|
-
*/
|
|
64
|
-
aliveCheck(): Promise<{
|
|
65
|
-
status: string;
|
|
66
|
-
statusCode: number;
|
|
67
|
-
}>;
|
|
68
|
-
/**
|
|
69
|
-
* Performs readiness health checks for clients configured with includeInReadinessCheck
|
|
70
|
-
*
|
|
71
|
-
* @returns Promise that resolves to { status: 'ok', statusCode: 200 } if ready
|
|
72
|
-
* @throws ServiceUnavailableError with statusCode 503 if not ready or health check fails
|
|
73
|
-
*/
|
|
74
|
-
readyCheck(): Promise<{
|
|
75
|
-
status: string;
|
|
76
|
-
statusCode: number;
|
|
77
|
-
}>;
|
|
78
|
-
/**
|
|
79
|
-
* Triggers graceful shutdown process
|
|
80
|
-
* Can be called manually or automatically via SIGTERM/SIGINT signal handlers
|
|
81
|
-
*
|
|
82
|
-
* @param signal - Signal name (e.g., 'SIGTERM', 'SIGINT', 'MANUAL')
|
|
83
|
-
*/
|
|
84
|
-
shutdown(signal?: string): Promise<void>;
|
|
85
|
-
}
|
|
86
|
-
//#endregion
|
|
87
|
-
export { HealthManager };
|
|
88
|
-
//# sourceMappingURL=health-manager.d.cts.map
|
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
import { HealthManagerOptions, ServerConfig } from "./types.js";
|
|
2
|
-
|
|
3
|
-
//#region src/health-manager/health-manager.d.ts
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Manages application health state and graceful shutdown for Kubernetes liveness/readiness probes
|
|
7
|
-
*
|
|
8
|
-
* Features:
|
|
9
|
-
* - Provides aliveCheck() and readyCheck() methods for liveness/readiness probes
|
|
10
|
-
* - Auto-registers SIGTERM/SIGINT handlers for graceful shutdown
|
|
11
|
-
* - Manages ready state during shutdown to fail readiness probes
|
|
12
|
-
*/
|
|
13
|
-
declare class HealthManager {
|
|
14
|
-
private readonly DEFAULT_CLIENT_OPTIONS;
|
|
15
|
-
private readonly DEFAULT_SERVER_OPTIONS;
|
|
16
|
-
private readonly DEFAULT_CONFIG;
|
|
17
|
-
private isShuttingDown;
|
|
18
|
-
private isReady;
|
|
19
|
-
private config;
|
|
20
|
-
private clientsMap;
|
|
21
|
-
private server;
|
|
22
|
-
private livenessChecks;
|
|
23
|
-
private readinessChecks;
|
|
24
|
-
private logger;
|
|
25
|
-
/**
|
|
26
|
-
* Creates a new HealthManager instance
|
|
27
|
-
*
|
|
28
|
-
* @param params Configuration options for health checks and shutdown behavior
|
|
29
|
-
*/
|
|
30
|
-
constructor(params: HealthManagerOptions);
|
|
31
|
-
/**
|
|
32
|
-
* Store clients with default health check and shutdown functions
|
|
33
|
-
* @private
|
|
34
|
-
*/
|
|
35
|
-
private storeClientsWithDefaults;
|
|
36
|
-
/**
|
|
37
|
-
* Register SIGTERM and SIGINT signal listeners
|
|
38
|
-
* @private
|
|
39
|
-
*/
|
|
40
|
-
private setupSignalHandlers;
|
|
41
|
-
/**
|
|
42
|
-
* Check if liveness optimization is safe to enable for a given client configuration
|
|
43
|
-
* If a client is in liveness but not readiness, we cannot skip liveness checks
|
|
44
|
-
* because the optimization relies on readiness passing, but this client isn't checked in readiness
|
|
45
|
-
* @private
|
|
46
|
-
*/
|
|
47
|
-
private canSafelySkipLivenessWhenReady;
|
|
48
|
-
/**
|
|
49
|
-
* Initialize health check arrays based on configured clients
|
|
50
|
-
* @private
|
|
51
|
-
*/
|
|
52
|
-
private initializeHealthChecks;
|
|
53
|
-
/**
|
|
54
|
-
* Attach an HTTP or HTTPS server to be managed during shutdown
|
|
55
|
-
* @param serverConfig Server configuration including the server instance and optional shutdown handler
|
|
56
|
-
*/
|
|
57
|
-
attachServer(serverConfig: ServerConfig): void;
|
|
58
|
-
/**
|
|
59
|
-
* Performs liveness health checks for clients configured with includeInLivenessCheck
|
|
60
|
-
*
|
|
61
|
-
* @returns Promise that resolves to { status: 'ok', statusCode: 200 } on success
|
|
62
|
-
* @throws ServiceUnavailableError with statusCode 503 if any health check fails
|
|
63
|
-
*/
|
|
64
|
-
aliveCheck(): Promise<{
|
|
65
|
-
status: string;
|
|
66
|
-
statusCode: number;
|
|
67
|
-
}>;
|
|
68
|
-
/**
|
|
69
|
-
* Performs readiness health checks for clients configured with includeInReadinessCheck
|
|
70
|
-
*
|
|
71
|
-
* @returns Promise that resolves to { status: 'ok', statusCode: 200 } if ready
|
|
72
|
-
* @throws ServiceUnavailableError with statusCode 503 if not ready or health check fails
|
|
73
|
-
*/
|
|
74
|
-
readyCheck(): Promise<{
|
|
75
|
-
status: string;
|
|
76
|
-
statusCode: number;
|
|
77
|
-
}>;
|
|
78
|
-
/**
|
|
79
|
-
* Triggers graceful shutdown process
|
|
80
|
-
* Can be called manually or automatically via SIGTERM/SIGINT signal handlers
|
|
81
|
-
*
|
|
82
|
-
* @param signal - Signal name (e.g., 'SIGTERM', 'SIGINT', 'MANUAL')
|
|
83
|
-
*/
|
|
84
|
-
shutdown(signal?: string): Promise<void>;
|
|
85
|
-
}
|
|
86
|
-
//#endregion
|
|
87
|
-
export { HealthManager };
|
|
88
|
-
//# sourceMappingURL=health-manager.d.ts.map
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{DEFAULT_CLIENT_HEALTHCHECK_FUNC_MAP as e}from"./health-check-handlers.js";import{DEFAULT_CLIENT_SHUTDOWN_HANDLERS_MAP as t,defaultServerShutdownHandler as n}from"./shutdown-handlers.js";import{setTimeout as r}from"node:timers/promises";import{ServiceUnavailableError as i}from"@autofleet/errors";var a=class{constructor(e){this.DEFAULT_CLIENT_OPTIONS={includeInLivenessCheck:!0,includeInReadinessCheck:!0},this.DEFAULT_SERVER_OPTIONS={runDefaultShutdownHandler:!0,name:`server`},this.DEFAULT_CONFIG={shutdownDelayMs:5e3,useExit0:!0,shouldSetupSignalHandlers:!0,enableLivenessOptimization:!0},this.isShuttingDown=!1,this.isReady=!1,this.clientsMap=new Map,this.livenessChecks=[],this.readinessChecks=[],this.canSafelySkipLivenessWhenReady=(e,t)=>!(e&&!t),this.config={...this.DEFAULT_CONFIG,...e.config??{}},this.logger=e.logger,e.server&&this.attachServer(e.server),this.storeClientsWithDefaults(e),this.initializeHealthChecks(),this.config.shouldSetupSignalHandlers&&this.setupSignalHandlers()}storeClientsWithDefaults(n){let r=n.clients;r&&Object.entries(r).forEach(([n,r])=>{if(!r)return;let i=(Array.isArray(r)?r:[r]).map(r=>{let i={...this.DEFAULT_CLIENT_OPTIONS,name:n,...r.options},a=e[n],o;r.healthCheck?o=r.healthCheck:a?o=e=>a({client:e.client,name:e.name,logger:this.logger}):(this.logger.warn(`No health check provided for client type '${n}' and no default implementation exists`),o=void 0);let s=t[n],c;return r.shutdown?c=r.shutdown:s?c=e=>s({client:e.client,signal:e.signal,name:e.name,logger:this.logger}):(this.logger.warn(`No shutdown handler provided for client type '${n}' and no default implementation exists`),c=void 0),{connection:r.connection,healthCheck:o,shutdown:c,options:i}});this.clientsMap.set(n,i)})}setupSignalHandlers(){this.logger.info(`Setting up global signal listeners for graceful shutdown`),process.on(`SIGTERM`,async()=>{await this.shutdown(`SIGTERM`)}),process.on(`SIGINT`,async()=>{await this.shutdown(`SIGINT`)})}initializeHealthChecks(){let e=!0;this.clientsMap.forEach(t=>{t.forEach(t=>{if(!t.healthCheck)return;let n=t.options?.includeInLivenessCheck??!0,r=t.options?.includeInReadinessCheck??!0;this.canSafelySkipLivenessWhenReady(n,r)||(e=!1),n&&this.livenessChecks.push({check:t.healthCheck,client:t.connection,name:t.options?.name||`unknown`,customHandlersPayload:t.options?.customHandlersPayload}),r&&this.readinessChecks.push({check:t.healthCheck,client:t.connection,name:t.options?.name||`unknown`,customHandlersPayload:t.options?.customHandlersPayload})})}),this.config.enableLivenessOptimization=this.config.enableLivenessOptimization&&e,this.config.enableLivenessOptimization?this.logger.info(`Liveness check optimization enabled - liveness checks will be skipped when pod is ready`):e||this.logger.warn(`Liveness check optimization disabled - some clients are in liveness checks but not in readiness checks`)}attachServer(e){this.server={server:e.server,shutdown:e.shutdown??(async()=>n(e.server,this.logger)),options:{...this.DEFAULT_SERVER_OPTIONS,...e.options??{}}}}async aliveCheck(){if(this.isShuttingDown||this.config.enableLivenessOptimization&&this.isReady)return{statusCode:200,status:`ok`};try{return await Promise.all(this.livenessChecks.map(({check:e,client:t,name:n,customHandlersPayload:r})=>e({client:t,name:n,customHandlersPayload:r}))),{statusCode:200,status:`ok`}}catch(e){let t=new i(`Liveness probe failed: ${e.message}`);throw t.stack=e.stack,t}}async readyCheck(){if(this.isShuttingDown)throw this.isReady=!1,new i(`Readiness probe failed: Application is shutting down`);try{return await Promise.all(this.readinessChecks.map(({check:e,client:t,name:n,customHandlersPayload:r})=>e({client:t,name:n,customHandlersPayload:r}))),this.isReady=!0,{statusCode:200,status:`ok`}}catch(e){this.isReady=!1;let t=new i(`Readiness probe failed: ${e.message}`);throw t.stack=e.stack,t}}async shutdown(e=`MANUAL`){try{if(this.isShuttingDown){this.logger.warn(`Shutdown already in progress`);return}let{shutdownDelayMs:t,useExit0:n,onShutdown:i,beforeShutdown:a}=this.config;this.isShuttingDown=!0,this.isReady=!1,this.logger.info(`${e} received: setting readiness state to false`),await a?.(),this.logger.info(`Waiting ${t}ms before shutdown...`),await r(t);let o=[];this.clientsMap.forEach(e=>{e.forEach(e=>{e.shutdown&&o.push(e.options?.name||`unknown`)})}),this.logger.info(`Executing shutdown hooks...`,{clients:o});let s=[];this.clientsMap.forEach(t=>{t.forEach(t=>{t.shutdown&&s.push(t.shutdown({signal:e,client:t.connection,name:t.options?.name||`unknown`,customHandlersPayload:t.options?.customHandlersPayload}))})}),await Promise.allSettled(s),await i?.(),this.server?.options?.runDefaultShutdownHandler&&(this.logger.info(`Shutting down server...`),await this.server?.shutdown?.()),this.logger.info(`Shutdown process completed`),n&&(this.logger.info(`Exiting process after ${e}`),process.exit(0))}catch(t){this.logger.error(`Error during shutdown process, forcing process exit despite shutdown error`,{error:t,signal:e}),process.exit(1)}}};export{a as HealthManager};
|
|
2
|
-
//# sourceMappingURL=health-manager.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"health-manager.js","names":["client","healthCheck: ((options: { client: any; name: string; customHandlersPayload?: any; }) => Promise<void>) | undefined","options","shutdown: ((options: { signal?: string; client: any; name: string; customHandlersPayload?: any; }) => Promise<void>) | undefined","error: any","clientNames: string[]","shutdownPromises: Promise<any>[]"],"sources":["../../src/health-manager/health-manager.ts"],"sourcesContent":["import { setTimeout } from 'node:timers/promises';\nimport { ServiceUnavailableError } from '@autofleet/errors';\nimport type {\n ClientConfig,\n HealthManagerConfig,\n HealthManagerOptions,\n ClientType,\n ServerConfig,\n} from './types';\nimport type { LoggerInstanceManager } from '@autofleet/logger';\nimport { DEFAULT_CLIENT_HEALTHCHECK_FUNC_MAP } from './health-check-handlers';\nimport { DEFAULT_CLIENT_SHUTDOWN_HANDLERS_MAP, defaultServerShutdownHandler } from './shutdown-handlers';\n\n/**\n * Manages application health state and graceful shutdown for Kubernetes liveness/readiness probes\n *\n * Features:\n * - Provides aliveCheck() and readyCheck() methods for liveness/readiness probes\n * - Auto-registers SIGTERM/SIGINT handlers for graceful shutdown\n * - Manages ready state during shutdown to fail readiness probes\n */\nexport class HealthManager {\n private readonly DEFAULT_CLIENT_OPTIONS = {\n includeInLivenessCheck: true,\n includeInReadinessCheck: true,\n };\n\n private readonly DEFAULT_SERVER_OPTIONS = {\n runDefaultShutdownHandler: true,\n name: 'server',\n };\n\n private readonly DEFAULT_CONFIG: HealthManagerConfig = {\n shutdownDelayMs: 5_000,\n useExit0: true,\n shouldSetupSignalHandlers: true,\n enableLivenessOptimization: true,\n };\n\n private isShuttingDown = false;\n private isReady = false;\n\n private config: HealthManagerConfig;\n\n private clientsMap = new Map<string, ClientConfig<any>[]>();\n private server: Required<ServerConfig> | undefined;\n\n private livenessChecks: { check: (options: { client: any; name: string; customHandlersPayload?: any; }) => Promise<void>; client: any; name: string; customHandlersPayload?: any; }[] = [];\n private readinessChecks: { check: (options: { client: any; name: string; customHandlersPayload?: any; }) => Promise<void>; client: any; name: string; customHandlersPayload?: any; }[] = [];\n\n private logger: LoggerInstanceManager;\n\n /**\n * Creates a new HealthManager instance\n *\n * @param params Configuration options for health checks and shutdown behavior\n */\n constructor(params: HealthManagerOptions) {\n this.config = {\n ...this.DEFAULT_CONFIG,\n ...(params.config ?? {}),\n };\n\n this.logger = params.logger;\n if (params.server) {\n this.attachServer(params.server);\n }\n\n this.storeClientsWithDefaults(params);\n\n this.initializeHealthChecks();\n\n if (this.config.shouldSetupSignalHandlers) {\n this.setupSignalHandlers();\n }\n }\n\n /**\n * Store clients with default health check and shutdown functions\n * @private\n */\n private storeClientsWithDefaults(params: HealthManagerOptions): void {\n const clients = params.clients;\n if (!clients) {\n return;\n }\n\n Object.entries(clients).forEach(([type, client]) => {\n if (!client) {\n return;\n }\n\n const clientsArray = Array.isArray(client) ? client : [client];\n\n // Apply default values to each client config\n const clientsWithDefaults = clientsArray.map((client) => {\n const options = {\n ...this.DEFAULT_CLIENT_OPTIONS,\n name: type,\n ...client.options,\n };\n\n const defaultHealthCheck = DEFAULT_CLIENT_HEALTHCHECK_FUNC_MAP[type as ClientType];\n let healthCheck: ((options: { client: any; name: string; customHandlersPayload?: any; }) => Promise<void>) | undefined;\n\n if (client.healthCheck) {\n healthCheck = client.healthCheck;\n } else if (defaultHealthCheck) {\n healthCheck = (options: { client: any; name: string; customHandlersPayload?: any; }) => defaultHealthCheck({ client: options.client, name: options.name, logger: this.logger });\n } else {\n this.logger.warn(`No health check provided for client type '${type}' and no default implementation exists`);\n healthCheck = undefined;\n }\n\n const defaultShutdown = DEFAULT_CLIENT_SHUTDOWN_HANDLERS_MAP[type as ClientType];\n let shutdown: ((options: { signal?: string; client: any; name: string; customHandlersPayload?: any; }) => Promise<void>) | undefined;\n\n if (client.shutdown) {\n shutdown = client.shutdown;\n } else if (defaultShutdown) {\n shutdown = (options: { signal?: string; client: any; name: string; customHandlersPayload?: any; }) => defaultShutdown(\n { client: options.client, signal: options.signal, name: options.name, logger: this.logger },\n );\n } else {\n this.logger.warn(`No shutdown handler provided for client type '${type}' and no default implementation exists`);\n shutdown = undefined;\n }\n\n return {\n connection: client.connection,\n healthCheck,\n shutdown,\n options,\n };\n });\n\n this.clientsMap.set(type, clientsWithDefaults);\n });\n }\n\n /**\n * Register SIGTERM and SIGINT signal listeners\n * @private\n */\n private setupSignalHandlers(): void {\n this.logger.info('Setting up global signal listeners for graceful shutdown');\n\n process.on('SIGTERM', async () => {\n await this.shutdown('SIGTERM');\n });\n\n process.on('SIGINT', async () => {\n await this.shutdown('SIGINT');\n });\n }\n\n /**\n * Check if liveness optimization is safe to enable for a given client configuration\n * If a client is in liveness but not readiness, we cannot skip liveness checks\n * because the optimization relies on readiness passing, but this client isn't checked in readiness\n * @private\n */\n private canSafelySkipLivenessWhenReady = (includeInLiveness: boolean, includeInReadiness: boolean): boolean =>\n !(includeInLiveness && !includeInReadiness);\n\n /**\n * Initialize health check arrays based on configured clients\n * @private\n */\n private initializeHealthChecks(): void {\n let allClientsAllowLivenessOptimization = true;\n\n this.clientsMap.forEach((clients) => {\n clients.forEach((client) => {\n if (!client.healthCheck) {\n return;\n }\n\n const includeInLiveness = client.options?.includeInLivenessCheck ?? true;\n const includeInReadiness = client.options?.includeInReadinessCheck ?? true;\n\n // Check if this client configuration allows liveness optimization\n if (!this.canSafelySkipLivenessWhenReady(includeInLiveness, includeInReadiness)) {\n allClientsAllowLivenessOptimization = false;\n }\n\n if (includeInLiveness) {\n this.livenessChecks.push({\n check: client.healthCheck,\n client: client.connection,\n name: client.options?.name || 'unknown',\n customHandlersPayload: client.options?.customHandlersPayload,\n });\n }\n\n if (includeInReadiness) {\n this.readinessChecks.push({\n check: client.healthCheck,\n client: client.connection,\n name: client.options?.name || 'unknown',\n customHandlersPayload: client.options?.customHandlersPayload,\n });\n }\n });\n });\n\n // Apply optimization setting: only enable if user requested it AND all clients allow it\n this.config.enableLivenessOptimization = this.config.enableLivenessOptimization && allClientsAllowLivenessOptimization;\n\n // Log optimization status\n if (this.config.enableLivenessOptimization) {\n this.logger.info('Liveness check optimization enabled - liveness checks will be skipped when pod is ready');\n } else if (!allClientsAllowLivenessOptimization) {\n this.logger.warn('Liveness check optimization disabled - some clients are in liveness checks but not in readiness checks');\n }\n }\n\n /**\n * Attach an HTTP or HTTPS server to be managed during shutdown\n * @param serverConfig Server configuration including the server instance and optional shutdown handler\n */\n attachServer(serverConfig: ServerConfig): void {\n this.server = {\n server: serverConfig.server,\n shutdown: serverConfig.shutdown ?? (async () => defaultServerShutdownHandler(serverConfig.server, this.logger)),\n options: {\n ...this.DEFAULT_SERVER_OPTIONS,\n ...(serverConfig.options ?? {}),\n },\n };\n }\n\n /**\n * Performs liveness health checks for clients configured with includeInLivenessCheck\n *\n * @returns Promise that resolves to { status: 'ok', statusCode: 200 } on success\n * @throws ServiceUnavailableError with statusCode 503 if any health check fails\n */\n async aliveCheck(): Promise<{ status: string; statusCode: number; }> {\n if (this.isShuttingDown) {\n return { statusCode: 200, status: 'ok' };\n }\n\n // Skip liveness check if optimization is enabled and pod is already ready\n if (this.config.enableLivenessOptimization && this.isReady) {\n return { statusCode: 200, status: 'ok' };\n }\n\n try {\n await Promise.all(\n this.livenessChecks.map(({ check, client, name, customHandlersPayload }) =>\n check({ client, name, customHandlersPayload }),\n ),\n );\n\n return { statusCode: 200, status: 'ok' };\n } catch (error: any) {\n const err = new ServiceUnavailableError(`Liveness probe failed: ${error.message}`);\n err.stack = error.stack;\n throw err;\n }\n }\n\n /**\n * Performs readiness health checks for clients configured with includeInReadinessCheck\n *\n * @returns Promise that resolves to { status: 'ok', statusCode: 200 } if ready\n * @throws ServiceUnavailableError with statusCode 503 if not ready or health check fails\n */\n async readyCheck(): Promise<{ status: string; statusCode: number; }> {\n if (this.isShuttingDown) {\n this.isReady = false;\n throw new ServiceUnavailableError('Readiness probe failed: Application is shutting down');\n }\n\n try {\n await Promise.all(\n this.readinessChecks.map(({ check, client, name, customHandlersPayload }) =>\n check({ client, name, customHandlersPayload }),\n ),\n );\n this.isReady = true;\n\n return { statusCode: 200, status: 'ok' };\n } catch (error: any) {\n this.isReady = false;\n const err = new ServiceUnavailableError(`Readiness probe failed: ${error.message}`);\n err.stack = error.stack;\n throw err;\n }\n }\n\n /**\n * Triggers graceful shutdown process\n * Can be called manually or automatically via SIGTERM/SIGINT signal handlers\n *\n * @param signal - Signal name (e.g., 'SIGTERM', 'SIGINT', 'MANUAL')\n */\n async shutdown(signal = 'MANUAL'): Promise<void> {\n try {\n if (this.isShuttingDown) {\n this.logger.warn('Shutdown already in progress');\n return;\n }\n\n const { shutdownDelayMs, useExit0, onShutdown, beforeShutdown } = this.config;\n\n this.isShuttingDown = true;\n this.isReady = false;\n\n this.logger.info(`${signal} received: setting readiness state to false`);\n\n await beforeShutdown?.();\n\n this.logger.info(`Waiting ${shutdownDelayMs}ms before shutdown...`);\n await setTimeout(shutdownDelayMs);\n\n // Collect client names that have shutdown handlers\n const clientNames: string[] = [];\n this.clientsMap.forEach((clients) => {\n clients.forEach((client) => {\n if (client.shutdown) {\n clientNames.push(client.options?.name || 'unknown');\n }\n });\n });\n\n this.logger.info('Executing shutdown hooks...', { clients: clientNames });\n\n const shutdownPromises: Promise<any>[] = [];\n this.clientsMap.forEach((clients) => {\n clients.forEach((client) => {\n if (client.shutdown) {\n shutdownPromises.push(client.shutdown({\n signal,\n client: client.connection,\n name: client.options?.name || 'unknown',\n customHandlersPayload: client.options?.customHandlersPayload,\n }));\n }\n });\n });\n\n await Promise.allSettled(shutdownPromises);\n\n await onShutdown?.();\n\n if (this.server?.options?.runDefaultShutdownHandler) {\n this.logger.info('Shutting down server...');\n await this.server?.shutdown?.();\n }\n\n this.logger.info('Shutdown process completed');\n\n if (useExit0) {\n this.logger.info(`Exiting process after ${signal}`);\n process.exit(0);\n }\n } catch (error: any) {\n this.logger.error('Error during shutdown process, forcing process exit despite shutdown error', { error, signal });\n process.exit(1);\n }\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
const e=require(`../_virtual/rolldown_runtime.cjs`),t=require(`./types.cjs`);let n=require(`http-terminator`);const r={[t.CLIENT_TYPES.REDIS]:async e=>{try{await e.client.quit?.()}catch(t){throw e.logger.error(`Failed to shutdown redis client '${e.name}'`,{error:t}),t}},[t.CLIENT_TYPES.SEQUELIZE]:async e=>{try{await e.client.close?.()}catch(t){throw e.logger.error(`Failed to shutdown sequelize client '${e.name}'`,{error:t}),t}},[t.CLIENT_TYPES.ELASTIC_SEARCH]:async e=>{try{await e.client.close?.()}catch(t){throw e.logger.error(`Failed to shutdown elasticsearch client '${e.name}'`,{error:t}),t}},[t.CLIENT_TYPES.RABBIT]:async e=>{try{await e.client.gracefulShutdown?.(e.signal)}catch(t){throw e.logger.error(`Failed to shutdown rabbit client '${e.name}'`,{error:t}),t}},[t.CLIENT_TYPES.EVENTS]:async e=>{try{await e.client.exitHandler?.(e.signal)}catch(t){throw e.logger.error(`Failed to shutdown events client '${e.name}'`,{error:t}),t}}},i=async(e,t)=>{try{await(0,n.createHttpTerminator)({server:e}).terminate()}catch(e){throw t.error(`Failed to shutdown server: ${e instanceof Error?e.message:String(e)}`),e}};exports.DEFAULT_CLIENT_SHUTDOWN_HANDLERS_MAP=r,exports.defaultServerShutdownHandler=i;
|
|
2
|
-
//# sourceMappingURL=shutdown-handlers.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"shutdown-handlers.cjs","names":["DEFAULT_CLIENT_SHUTDOWN_HANDLERS_MAP: Record<ClientType, (options: { client: any; name: string; signal?: string; logger: LoggerInstanceManager; }) => Promise<void>>","CLIENT_TYPES"],"sources":["../../src/health-manager/shutdown-handlers.ts"],"sourcesContent":["import {\n createHttpTerminator,\n} from 'http-terminator';\nimport type { Server as HttpServer } from 'node:http';\nimport type { Server as HttpsServer } from 'node:https';\nimport type { LoggerInstanceManager } from '@autofleet/logger';\nimport type { ClientType } from './types';\nimport { CLIENT_TYPES } from './types';\n\nexport const DEFAULT_CLIENT_SHUTDOWN_HANDLERS_MAP: Record<ClientType, (options: { client: any; name: string; signal?: string; logger: LoggerInstanceManager; }) => Promise<void>> = {\n [CLIENT_TYPES.REDIS]: async (options) => {\n try {\n await options.client.quit?.();\n } catch (error) {\n options.logger.error(`Failed to shutdown redis client '${options.name}'`, { error });\n throw error;\n }\n },\n [CLIENT_TYPES.SEQUELIZE]: async (options) => {\n try {\n await options.client.close?.();\n } catch (error) {\n options.logger.error(`Failed to shutdown sequelize client '${options.name}'`, { error });\n throw error;\n }\n },\n [CLIENT_TYPES.ELASTIC_SEARCH]: async (options) => {\n try {\n await options.client.close?.();\n } catch (error) {\n options.logger.error(`Failed to shutdown elasticsearch client '${options.name}'`, { error });\n throw error;\n }\n },\n [CLIENT_TYPES.RABBIT]: async (options) => {\n try {\n await options.client.gracefulShutdown?.(options.signal);\n } catch (error) {\n options.logger.error(`Failed to shutdown rabbit client '${options.name}'`, { error });\n throw error;\n }\n },\n [CLIENT_TYPES.EVENTS]: async (options) => {\n try {\n await options.client.exitHandler?.(options.signal);\n } catch (error) {\n options.logger.error(`Failed to shutdown events client '${options.name}'`, { error });\n throw error;\n }\n },\n};\n\nexport const defaultServerShutdownHandler = async (server: HttpServer | HttpsServer, logger: LoggerInstanceManager): Promise<void> => {\n try {\n const httpTerminator = createHttpTerminator({\n server,\n });\n await httpTerminator.terminate();\n } catch (error) {\n logger.error(`Failed to shutdown server: ${error instanceof Error ? error.message : String(error)}`);\n throw error;\n }\n};\n"],"mappings":"8GASA,MAAaA,EAAuK,EACjLC,EAAAA,aAAa,OAAQ,KAAO,IAAY,CACvC,GAAI,CACF,MAAM,EAAQ,OAAO,QAAQ,OACtB,EAAO,CAEd,MADA,EAAQ,OAAO,MAAM,oCAAoC,EAAQ,KAAK,GAAI,CAAE,QAAO,CAAC,CAC9E,KAGTA,EAAAA,aAAa,WAAY,KAAO,IAAY,CAC3C,GAAI,CACF,MAAM,EAAQ,OAAO,SAAS,OACvB,EAAO,CAEd,MADA,EAAQ,OAAO,MAAM,wCAAwC,EAAQ,KAAK,GAAI,CAAE,QAAO,CAAC,CAClF,KAGTA,EAAAA,aAAa,gBAAiB,KAAO,IAAY,CAChD,GAAI,CACF,MAAM,EAAQ,OAAO,SAAS,OACvB,EAAO,CAEd,MADA,EAAQ,OAAO,MAAM,4CAA4C,EAAQ,KAAK,GAAI,CAAE,QAAO,CAAC,CACtF,KAGTA,EAAAA,aAAa,QAAS,KAAO,IAAY,CACxC,GAAI,CACF,MAAM,EAAQ,OAAO,mBAAmB,EAAQ,OAAO,OAChD,EAAO,CAEd,MADA,EAAQ,OAAO,MAAM,qCAAqC,EAAQ,KAAK,GAAI,CAAE,QAAO,CAAC,CAC/E,KAGTA,EAAAA,aAAa,QAAS,KAAO,IAAY,CACxC,GAAI,CACF,MAAM,EAAQ,OAAO,cAAc,EAAQ,OAAO,OAC3C,EAAO,CAEd,MADA,EAAQ,OAAO,MAAM,qCAAqC,EAAQ,KAAK,GAAI,CAAE,QAAO,CAAC,CAC/E,IAGX,CAEY,EAA+B,MAAO,EAAkC,IAAiD,CACpI,GAAI,CAIF,MAAA,EAAA,EAAA,sBAH4C,CAC1C,SACD,CAAC,CACmB,WAAW,OACzB,EAAO,CAEd,MADA,EAAO,MAAM,8BAA8B,aAAiB,MAAQ,EAAM,QAAU,OAAO,EAAM,GAAG,CAC9F"}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{CLIENT_TYPES as e}from"./types.js";import{createHttpTerminator as t}from"http-terminator";const n={[e.REDIS]:async e=>{try{await e.client.quit?.()}catch(t){throw e.logger.error(`Failed to shutdown redis client '${e.name}'`,{error:t}),t}},[e.SEQUELIZE]:async e=>{try{await e.client.close?.()}catch(t){throw e.logger.error(`Failed to shutdown sequelize client '${e.name}'`,{error:t}),t}},[e.ELASTIC_SEARCH]:async e=>{try{await e.client.close?.()}catch(t){throw e.logger.error(`Failed to shutdown elasticsearch client '${e.name}'`,{error:t}),t}},[e.RABBIT]:async e=>{try{await e.client.gracefulShutdown?.(e.signal)}catch(t){throw e.logger.error(`Failed to shutdown rabbit client '${e.name}'`,{error:t}),t}},[e.EVENTS]:async e=>{try{await e.client.exitHandler?.(e.signal)}catch(t){throw e.logger.error(`Failed to shutdown events client '${e.name}'`,{error:t}),t}}},r=async(e,n)=>{try{await t({server:e}).terminate()}catch(e){throw n.error(`Failed to shutdown server: ${e instanceof Error?e.message:String(e)}`),e}};export{n as DEFAULT_CLIENT_SHUTDOWN_HANDLERS_MAP,r as defaultServerShutdownHandler};
|
|
2
|
-
//# sourceMappingURL=shutdown-handlers.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"shutdown-handlers.js","names":["DEFAULT_CLIENT_SHUTDOWN_HANDLERS_MAP: Record<ClientType, (options: { client: any; name: string; signal?: string; logger: LoggerInstanceManager; }) => Promise<void>>"],"sources":["../../src/health-manager/shutdown-handlers.ts"],"sourcesContent":["import {\n createHttpTerminator,\n} from 'http-terminator';\nimport type { Server as HttpServer } from 'node:http';\nimport type { Server as HttpsServer } from 'node:https';\nimport type { LoggerInstanceManager } from '@autofleet/logger';\nimport type { ClientType } from './types';\nimport { CLIENT_TYPES } from './types';\n\nexport const DEFAULT_CLIENT_SHUTDOWN_HANDLERS_MAP: Record<ClientType, (options: { client: any; name: string; signal?: string; logger: LoggerInstanceManager; }) => Promise<void>> = {\n [CLIENT_TYPES.REDIS]: async (options) => {\n try {\n await options.client.quit?.();\n } catch (error) {\n options.logger.error(`Failed to shutdown redis client '${options.name}'`, { error });\n throw error;\n }\n },\n [CLIENT_TYPES.SEQUELIZE]: async (options) => {\n try {\n await options.client.close?.();\n } catch (error) {\n options.logger.error(`Failed to shutdown sequelize client '${options.name}'`, { error });\n throw error;\n }\n },\n [CLIENT_TYPES.ELASTIC_SEARCH]: async (options) => {\n try {\n await options.client.close?.();\n } catch (error) {\n options.logger.error(`Failed to shutdown elasticsearch client '${options.name}'`, { error });\n throw error;\n }\n },\n [CLIENT_TYPES.RABBIT]: async (options) => {\n try {\n await options.client.gracefulShutdown?.(options.signal);\n } catch (error) {\n options.logger.error(`Failed to shutdown rabbit client '${options.name}'`, { error });\n throw error;\n }\n },\n [CLIENT_TYPES.EVENTS]: async (options) => {\n try {\n await options.client.exitHandler?.(options.signal);\n } catch (error) {\n options.logger.error(`Failed to shutdown events client '${options.name}'`, { error });\n throw error;\n }\n },\n};\n\nexport const defaultServerShutdownHandler = async (server: HttpServer | HttpsServer, logger: LoggerInstanceManager): Promise<void> => {\n try {\n const httpTerminator = createHttpTerminator({\n server,\n });\n await httpTerminator.terminate();\n } catch (error) {\n logger.error(`Failed to shutdown server: ${error instanceof Error ? error.message : String(error)}`);\n throw error;\n }\n};\n"],"mappings":"iGASA,MAAaA,EAAuK,EACjL,EAAa,OAAQ,KAAO,IAAY,CACvC,GAAI,CACF,MAAM,EAAQ,OAAO,QAAQ,OACtB,EAAO,CAEd,MADA,EAAQ,OAAO,MAAM,oCAAoC,EAAQ,KAAK,GAAI,CAAE,QAAO,CAAC,CAC9E,KAGT,EAAa,WAAY,KAAO,IAAY,CAC3C,GAAI,CACF,MAAM,EAAQ,OAAO,SAAS,OACvB,EAAO,CAEd,MADA,EAAQ,OAAO,MAAM,wCAAwC,EAAQ,KAAK,GAAI,CAAE,QAAO,CAAC,CAClF,KAGT,EAAa,gBAAiB,KAAO,IAAY,CAChD,GAAI,CACF,MAAM,EAAQ,OAAO,SAAS,OACvB,EAAO,CAEd,MADA,EAAQ,OAAO,MAAM,4CAA4C,EAAQ,KAAK,GAAI,CAAE,QAAO,CAAC,CACtF,KAGT,EAAa,QAAS,KAAO,IAAY,CACxC,GAAI,CACF,MAAM,EAAQ,OAAO,mBAAmB,EAAQ,OAAO,OAChD,EAAO,CAEd,MADA,EAAQ,OAAO,MAAM,qCAAqC,EAAQ,KAAK,GAAI,CAAE,QAAO,CAAC,CAC/E,KAGT,EAAa,QAAS,KAAO,IAAY,CACxC,GAAI,CACF,MAAM,EAAQ,OAAO,cAAc,EAAQ,OAAO,OAC3C,EAAO,CAEd,MADA,EAAQ,OAAO,MAAM,qCAAqC,EAAQ,KAAK,GAAI,CAAE,QAAO,CAAC,CAC/E,IAGX,CAEY,EAA+B,MAAO,EAAkC,IAAiD,CACpI,GAAI,CAIF,MAHuB,EAAqB,CAC1C,SACD,CAAC,CACmB,WAAW,OACzB,EAAO,CAEd,MADA,EAAO,MAAM,8BAA8B,aAAiB,MAAQ,EAAM,QAAU,OAAO,EAAM,GAAG,CAC9F"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"types.cjs","names":[],"sources":["../../src/health-manager/types.ts"],"sourcesContent":["import type { LoggerInstanceManager } from '@autofleet/logger';\nimport type { Server as HttpServer } from 'node:http';\nimport type { Server as HttpsServer } from 'node:https';\n\n/**\n * Configuration for a single client (e.g., rabbit, sequelize, redis, elasticsearch)\n * Allows custom health checks and shutdown logic\n */\nexport interface ClientConfig<T = any, TPayload = any> {\n /** The actual connection instance */\n connection: T;\n\n /** Custom health check function (optional) - will be called during alive/ready checks with client connection and name */\n healthCheck?: (options: { client: T; name: string; customHandlersPayload?: TPayload; }) => Promise<void>;\n\n /** Custom shutdown function (optional) - will be called during graceful shutdown with signal name (e.g., 'SIGTERM', 'SIGINT'), client connection, and name */\n shutdown?: (options: { signal?: string; client: T; name: string; customHandlersPayload?: TPayload; }) => Promise<void>;\n\n /** Additional options specific to the client (optional) */\n options?: {\n /** Whether to include this client in liveness checks (default: true) */\n includeInLivenessCheck?: boolean;\n\n /** Whether to include this client in readiness checks (default: true) */\n includeInReadinessCheck?: boolean;\n\n /** Custom name for this client (used in logging) */\n name?: string;\n\n /** Custom payload to pass to health check and shutdown handlers - use this to pass any additional data your handlers need */\n customHandlersPayload?: TPayload;\n };\n}\n\n/** Configuration for an HTTP or HTTPS server managed by HealthManager */\nexport interface ServerConfig {\n /** The HTTP or HTTPS server instance */\n server: HttpServer | HttpsServer;\n\n /** Custom shutdown function for the server (optional) - receives signal name (e.g., 'SIGTERM', 'SIGINT') */\n shutdown?: (signal?: string) => Promise<void>;\n\n /** Additional options specific to the server (optional) */\n options?: {\n /** Custom name for this server (used in logging) */\n name?: string;\n\n /** Whether to skip the default shutdown handler for this server */\n runDefaultShutdownHandler?: boolean;\n\n };\n}\n\n/**\n * General configuration options for the HealthManager\n */\nexport interface HealthManagerConfig {\n /**\n * Delay in milliseconds before shutting down after SIGTERM/SIGINT\n * This gives time for load balancers to stop routing traffic. Should be equal to or greater than readiness probe interval.\n * @default 5000\n */\n shutdownDelayMs?: number;\n\n /**\n * Whether to call process.exit(0) after shutdown sequence completes\n * @default true\n */\n useExit0?: boolean;\n\n /** Whether to auto-setup SIGTERM/SIGINT handlers for graceful shutdown\n * @default true\n */\n shouldSetupSignalHandlers?: boolean;\n\n /**\n * Global shutdown hook called before all clients are shut down\n * @default undefined\n */\n beforeShutdown?: (() => Promise<void>) | undefined;\n\n /**\n * Global shutdown hook called after all clients are shut down\n * @default undefined\n */\n onShutdown?: (() => Promise<void>) | undefined;\n\n /**\n * Enable liveness check optimization - if true and all clients are in both liveness and readiness checks,\n * liveness checks will be skipped when pod is already ready (readiness check passed)\n * @default true\n */\n enableLivenessOptimization?: boolean;\n}\n\n/**\n * List of clients and general configuration for HealthManager\n */\nexport interface HealthManagerOptions {\n /** Client configurations */\n clients?: {\n /** RabbitMQ client configuration - can be a single config or array of configs */\n rabbit?: ClientConfig<any> | ClientConfig<any>[];\n\n /** Sequelize instance configuration - can be a single config or array of configs */\n sequelize?: ClientConfig<any> | ClientConfig<any>[];\n\n /** Redis client configuration - can be a single config or array of configs */\n redis?: ClientConfig<any> | ClientConfig<any>[];\n\n /** Elasticsearch client configuration - can be a single config or array of configs */\n elasticsearch?: ClientConfig<any> | ClientConfig<any>[];\n };\n\n /** General configuration options */\n config?: HealthManagerConfig;\n\n /** Logger instance for logging messages */\n logger: LoggerInstanceManager;\n\n /** Optional HTTP or HTTPS server instance to manage during shutdown */\n server?: ServerConfig;\n}\n\nexport interface RedisClient {\n ping: () => Promise<string | void>;\n}\n\n/**\n * Sequelize database interface\n */\nexport interface SequelizeClient {\n query(sql: string | { query: string; values: unknown[]; }): Promise<any>;\n}\n\n/**\n * Elasticsearch client interface\n */\nexport interface ElasticsearchClient {\n ping: () => Promise<boolean>;\n}\n\nexport interface EventsClient {\n exitHandler: () => Promise<void>;\n}\n\n/**\n * RabbitMQ client interface\n */\nexport interface RabbitMQClient {\n isConnected: () => Promise<boolean> | boolean;\n}\n\nexport const CLIENT_TYPES = {\n RABBIT: 'rabbit',\n SEQUELIZE: 'sequelize',\n REDIS: 'redis',\n ELASTIC_SEARCH: 'elasticsearch',\n EVENTS: 'events',\n} as const;\n\nexport type ClientType = typeof CLIENT_TYPES[keyof typeof CLIENT_TYPES];\n"],"mappings":"AAyJA,MAAa,EAAe,CAC1B,OAAQ,SACR,UAAW,YACX,MAAO,QACP,eAAgB,gBAChB,OAAQ,SACT"}
|
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
import { LoggerInstanceManager } from "@autofleet/logger";
|
|
2
|
-
import { Server } from "node:http";
|
|
3
|
-
import { Server as Server$1 } from "node:https";
|
|
4
|
-
|
|
5
|
-
//#region src/health-manager/types.d.ts
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Configuration for a single client (e.g., rabbit, sequelize, redis, elasticsearch)
|
|
9
|
-
* Allows custom health checks and shutdown logic
|
|
10
|
-
*/
|
|
11
|
-
interface ClientConfig<T = any, TPayload = any> {
|
|
12
|
-
/** The actual connection instance */
|
|
13
|
-
connection: T;
|
|
14
|
-
/** Custom health check function (optional) - will be called during alive/ready checks with client connection and name */
|
|
15
|
-
healthCheck?: (options: {
|
|
16
|
-
client: T;
|
|
17
|
-
name: string;
|
|
18
|
-
customHandlersPayload?: TPayload;
|
|
19
|
-
}) => Promise<void>;
|
|
20
|
-
/** Custom shutdown function (optional) - will be called during graceful shutdown with signal name (e.g., 'SIGTERM', 'SIGINT'), client connection, and name */
|
|
21
|
-
shutdown?: (options: {
|
|
22
|
-
signal?: string;
|
|
23
|
-
client: T;
|
|
24
|
-
name: string;
|
|
25
|
-
customHandlersPayload?: TPayload;
|
|
26
|
-
}) => Promise<void>;
|
|
27
|
-
/** Additional options specific to the client (optional) */
|
|
28
|
-
options?: {
|
|
29
|
-
/** Whether to include this client in liveness checks (default: true) */
|
|
30
|
-
includeInLivenessCheck?: boolean;
|
|
31
|
-
/** Whether to include this client in readiness checks (default: true) */
|
|
32
|
-
includeInReadinessCheck?: boolean;
|
|
33
|
-
/** Custom name for this client (used in logging) */
|
|
34
|
-
name?: string;
|
|
35
|
-
/** Custom payload to pass to health check and shutdown handlers - use this to pass any additional data your handlers need */
|
|
36
|
-
customHandlersPayload?: TPayload;
|
|
37
|
-
};
|
|
38
|
-
}
|
|
39
|
-
/** Configuration for an HTTP or HTTPS server managed by HealthManager */
|
|
40
|
-
interface ServerConfig {
|
|
41
|
-
/** The HTTP or HTTPS server instance */
|
|
42
|
-
server: Server | Server$1;
|
|
43
|
-
/** Custom shutdown function for the server (optional) - receives signal name (e.g., 'SIGTERM', 'SIGINT') */
|
|
44
|
-
shutdown?: (signal?: string) => Promise<void>;
|
|
45
|
-
/** Additional options specific to the server (optional) */
|
|
46
|
-
options?: {
|
|
47
|
-
/** Custom name for this server (used in logging) */
|
|
48
|
-
name?: string;
|
|
49
|
-
/** Whether to skip the default shutdown handler for this server */
|
|
50
|
-
runDefaultShutdownHandler?: boolean;
|
|
51
|
-
};
|
|
52
|
-
}
|
|
53
|
-
/**
|
|
54
|
-
* General configuration options for the HealthManager
|
|
55
|
-
*/
|
|
56
|
-
interface HealthManagerConfig {
|
|
57
|
-
/**
|
|
58
|
-
* Delay in milliseconds before shutting down after SIGTERM/SIGINT
|
|
59
|
-
* This gives time for load balancers to stop routing traffic. Should be equal to or greater than readiness probe interval.
|
|
60
|
-
* @default 5000
|
|
61
|
-
*/
|
|
62
|
-
shutdownDelayMs?: number;
|
|
63
|
-
/**
|
|
64
|
-
* Whether to call process.exit(0) after shutdown sequence completes
|
|
65
|
-
* @default true
|
|
66
|
-
*/
|
|
67
|
-
useExit0?: boolean;
|
|
68
|
-
/** Whether to auto-setup SIGTERM/SIGINT handlers for graceful shutdown
|
|
69
|
-
* @default true
|
|
70
|
-
*/
|
|
71
|
-
shouldSetupSignalHandlers?: boolean;
|
|
72
|
-
/**
|
|
73
|
-
* Global shutdown hook called before all clients are shut down
|
|
74
|
-
* @default undefined
|
|
75
|
-
*/
|
|
76
|
-
beforeShutdown?: (() => Promise<void>) | undefined;
|
|
77
|
-
/**
|
|
78
|
-
* Global shutdown hook called after all clients are shut down
|
|
79
|
-
* @default undefined
|
|
80
|
-
*/
|
|
81
|
-
onShutdown?: (() => Promise<void>) | undefined;
|
|
82
|
-
/**
|
|
83
|
-
* Enable liveness check optimization - if true and all clients are in both liveness and readiness checks,
|
|
84
|
-
* liveness checks will be skipped when pod is already ready (readiness check passed)
|
|
85
|
-
* @default true
|
|
86
|
-
*/
|
|
87
|
-
enableLivenessOptimization?: boolean;
|
|
88
|
-
}
|
|
89
|
-
/**
|
|
90
|
-
* List of clients and general configuration for HealthManager
|
|
91
|
-
*/
|
|
92
|
-
interface HealthManagerOptions {
|
|
93
|
-
/** Client configurations */
|
|
94
|
-
clients?: {
|
|
95
|
-
/** RabbitMQ client configuration - can be a single config or array of configs */
|
|
96
|
-
rabbit?: ClientConfig<any> | ClientConfig<any>[];
|
|
97
|
-
/** Sequelize instance configuration - can be a single config or array of configs */
|
|
98
|
-
sequelize?: ClientConfig<any> | ClientConfig<any>[];
|
|
99
|
-
/** Redis client configuration - can be a single config or array of configs */
|
|
100
|
-
redis?: ClientConfig<any> | ClientConfig<any>[];
|
|
101
|
-
/** Elasticsearch client configuration - can be a single config or array of configs */
|
|
102
|
-
elasticsearch?: ClientConfig<any> | ClientConfig<any>[];
|
|
103
|
-
};
|
|
104
|
-
/** General configuration options */
|
|
105
|
-
config?: HealthManagerConfig;
|
|
106
|
-
/** Logger instance for logging messages */
|
|
107
|
-
logger: LoggerInstanceManager;
|
|
108
|
-
/** Optional HTTP or HTTPS server instance to manage during shutdown */
|
|
109
|
-
server?: ServerConfig;
|
|
110
|
-
}
|
|
111
|
-
//#endregion
|
|
112
|
-
export { HealthManagerOptions, ServerConfig };
|
|
113
|
-
//# sourceMappingURL=types.d.cts.map
|
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
import { LoggerInstanceManager } from "@autofleet/logger";
|
|
2
|
-
import { Server } from "node:http";
|
|
3
|
-
import { Server as Server$1 } from "node:https";
|
|
4
|
-
|
|
5
|
-
//#region src/health-manager/types.d.ts
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Configuration for a single client (e.g., rabbit, sequelize, redis, elasticsearch)
|
|
9
|
-
* Allows custom health checks and shutdown logic
|
|
10
|
-
*/
|
|
11
|
-
interface ClientConfig<T = any, TPayload = any> {
|
|
12
|
-
/** The actual connection instance */
|
|
13
|
-
connection: T;
|
|
14
|
-
/** Custom health check function (optional) - will be called during alive/ready checks with client connection and name */
|
|
15
|
-
healthCheck?: (options: {
|
|
16
|
-
client: T;
|
|
17
|
-
name: string;
|
|
18
|
-
customHandlersPayload?: TPayload;
|
|
19
|
-
}) => Promise<void>;
|
|
20
|
-
/** Custom shutdown function (optional) - will be called during graceful shutdown with signal name (e.g., 'SIGTERM', 'SIGINT'), client connection, and name */
|
|
21
|
-
shutdown?: (options: {
|
|
22
|
-
signal?: string;
|
|
23
|
-
client: T;
|
|
24
|
-
name: string;
|
|
25
|
-
customHandlersPayload?: TPayload;
|
|
26
|
-
}) => Promise<void>;
|
|
27
|
-
/** Additional options specific to the client (optional) */
|
|
28
|
-
options?: {
|
|
29
|
-
/** Whether to include this client in liveness checks (default: true) */
|
|
30
|
-
includeInLivenessCheck?: boolean;
|
|
31
|
-
/** Whether to include this client in readiness checks (default: true) */
|
|
32
|
-
includeInReadinessCheck?: boolean;
|
|
33
|
-
/** Custom name for this client (used in logging) */
|
|
34
|
-
name?: string;
|
|
35
|
-
/** Custom payload to pass to health check and shutdown handlers - use this to pass any additional data your handlers need */
|
|
36
|
-
customHandlersPayload?: TPayload;
|
|
37
|
-
};
|
|
38
|
-
}
|
|
39
|
-
/** Configuration for an HTTP or HTTPS server managed by HealthManager */
|
|
40
|
-
interface ServerConfig {
|
|
41
|
-
/** The HTTP or HTTPS server instance */
|
|
42
|
-
server: Server | Server$1;
|
|
43
|
-
/** Custom shutdown function for the server (optional) - receives signal name (e.g., 'SIGTERM', 'SIGINT') */
|
|
44
|
-
shutdown?: (signal?: string) => Promise<void>;
|
|
45
|
-
/** Additional options specific to the server (optional) */
|
|
46
|
-
options?: {
|
|
47
|
-
/** Custom name for this server (used in logging) */
|
|
48
|
-
name?: string;
|
|
49
|
-
/** Whether to skip the default shutdown handler for this server */
|
|
50
|
-
runDefaultShutdownHandler?: boolean;
|
|
51
|
-
};
|
|
52
|
-
}
|
|
53
|
-
/**
|
|
54
|
-
* General configuration options for the HealthManager
|
|
55
|
-
*/
|
|
56
|
-
interface HealthManagerConfig {
|
|
57
|
-
/**
|
|
58
|
-
* Delay in milliseconds before shutting down after SIGTERM/SIGINT
|
|
59
|
-
* This gives time for load balancers to stop routing traffic. Should be equal to or greater than readiness probe interval.
|
|
60
|
-
* @default 5000
|
|
61
|
-
*/
|
|
62
|
-
shutdownDelayMs?: number;
|
|
63
|
-
/**
|
|
64
|
-
* Whether to call process.exit(0) after shutdown sequence completes
|
|
65
|
-
* @default true
|
|
66
|
-
*/
|
|
67
|
-
useExit0?: boolean;
|
|
68
|
-
/** Whether to auto-setup SIGTERM/SIGINT handlers for graceful shutdown
|
|
69
|
-
* @default true
|
|
70
|
-
*/
|
|
71
|
-
shouldSetupSignalHandlers?: boolean;
|
|
72
|
-
/**
|
|
73
|
-
* Global shutdown hook called before all clients are shut down
|
|
74
|
-
* @default undefined
|
|
75
|
-
*/
|
|
76
|
-
beforeShutdown?: (() => Promise<void>) | undefined;
|
|
77
|
-
/**
|
|
78
|
-
* Global shutdown hook called after all clients are shut down
|
|
79
|
-
* @default undefined
|
|
80
|
-
*/
|
|
81
|
-
onShutdown?: (() => Promise<void>) | undefined;
|
|
82
|
-
/**
|
|
83
|
-
* Enable liveness check optimization - if true and all clients are in both liveness and readiness checks,
|
|
84
|
-
* liveness checks will be skipped when pod is already ready (readiness check passed)
|
|
85
|
-
* @default true
|
|
86
|
-
*/
|
|
87
|
-
enableLivenessOptimization?: boolean;
|
|
88
|
-
}
|
|
89
|
-
/**
|
|
90
|
-
* List of clients and general configuration for HealthManager
|
|
91
|
-
*/
|
|
92
|
-
interface HealthManagerOptions {
|
|
93
|
-
/** Client configurations */
|
|
94
|
-
clients?: {
|
|
95
|
-
/** RabbitMQ client configuration - can be a single config or array of configs */
|
|
96
|
-
rabbit?: ClientConfig<any> | ClientConfig<any>[];
|
|
97
|
-
/** Sequelize instance configuration - can be a single config or array of configs */
|
|
98
|
-
sequelize?: ClientConfig<any> | ClientConfig<any>[];
|
|
99
|
-
/** Redis client configuration - can be a single config or array of configs */
|
|
100
|
-
redis?: ClientConfig<any> | ClientConfig<any>[];
|
|
101
|
-
/** Elasticsearch client configuration - can be a single config or array of configs */
|
|
102
|
-
elasticsearch?: ClientConfig<any> | ClientConfig<any>[];
|
|
103
|
-
};
|
|
104
|
-
/** General configuration options */
|
|
105
|
-
config?: HealthManagerConfig;
|
|
106
|
-
/** Logger instance for logging messages */
|
|
107
|
-
logger: LoggerInstanceManager;
|
|
108
|
-
/** Optional HTTP or HTTPS server instance to manage during shutdown */
|
|
109
|
-
server?: ServerConfig;
|
|
110
|
-
}
|
|
111
|
-
//#endregion
|
|
112
|
-
export { HealthManagerOptions, ServerConfig };
|
|
113
|
-
//# sourceMappingURL=types.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","names":[],"sources":["../../src/health-manager/types.ts"],"sourcesContent":["import type { LoggerInstanceManager } from '@autofleet/logger';\nimport type { Server as HttpServer } from 'node:http';\nimport type { Server as HttpsServer } from 'node:https';\n\n/**\n * Configuration for a single client (e.g., rabbit, sequelize, redis, elasticsearch)\n * Allows custom health checks and shutdown logic\n */\nexport interface ClientConfig<T = any, TPayload = any> {\n /** The actual connection instance */\n connection: T;\n\n /** Custom health check function (optional) - will be called during alive/ready checks with client connection and name */\n healthCheck?: (options: { client: T; name: string; customHandlersPayload?: TPayload; }) => Promise<void>;\n\n /** Custom shutdown function (optional) - will be called during graceful shutdown with signal name (e.g., 'SIGTERM', 'SIGINT'), client connection, and name */\n shutdown?: (options: { signal?: string; client: T; name: string; customHandlersPayload?: TPayload; }) => Promise<void>;\n\n /** Additional options specific to the client (optional) */\n options?: {\n /** Whether to include this client in liveness checks (default: true) */\n includeInLivenessCheck?: boolean;\n\n /** Whether to include this client in readiness checks (default: true) */\n includeInReadinessCheck?: boolean;\n\n /** Custom name for this client (used in logging) */\n name?: string;\n\n /** Custom payload to pass to health check and shutdown handlers - use this to pass any additional data your handlers need */\n customHandlersPayload?: TPayload;\n };\n}\n\n/** Configuration for an HTTP or HTTPS server managed by HealthManager */\nexport interface ServerConfig {\n /** The HTTP or HTTPS server instance */\n server: HttpServer | HttpsServer;\n\n /** Custom shutdown function for the server (optional) - receives signal name (e.g., 'SIGTERM', 'SIGINT') */\n shutdown?: (signal?: string) => Promise<void>;\n\n /** Additional options specific to the server (optional) */\n options?: {\n /** Custom name for this server (used in logging) */\n name?: string;\n\n /** Whether to skip the default shutdown handler for this server */\n runDefaultShutdownHandler?: boolean;\n\n };\n}\n\n/**\n * General configuration options for the HealthManager\n */\nexport interface HealthManagerConfig {\n /**\n * Delay in milliseconds before shutting down after SIGTERM/SIGINT\n * This gives time for load balancers to stop routing traffic. Should be equal to or greater than readiness probe interval.\n * @default 5000\n */\n shutdownDelayMs?: number;\n\n /**\n * Whether to call process.exit(0) after shutdown sequence completes\n * @default true\n */\n useExit0?: boolean;\n\n /** Whether to auto-setup SIGTERM/SIGINT handlers for graceful shutdown\n * @default true\n */\n shouldSetupSignalHandlers?: boolean;\n\n /**\n * Global shutdown hook called before all clients are shut down\n * @default undefined\n */\n beforeShutdown?: (() => Promise<void>) | undefined;\n\n /**\n * Global shutdown hook called after all clients are shut down\n * @default undefined\n */\n onShutdown?: (() => Promise<void>) | undefined;\n\n /**\n * Enable liveness check optimization - if true and all clients are in both liveness and readiness checks,\n * liveness checks will be skipped when pod is already ready (readiness check passed)\n * @default true\n */\n enableLivenessOptimization?: boolean;\n}\n\n/**\n * List of clients and general configuration for HealthManager\n */\nexport interface HealthManagerOptions {\n /** Client configurations */\n clients?: {\n /** RabbitMQ client configuration - can be a single config or array of configs */\n rabbit?: ClientConfig<any> | ClientConfig<any>[];\n\n /** Sequelize instance configuration - can be a single config or array of configs */\n sequelize?: ClientConfig<any> | ClientConfig<any>[];\n\n /** Redis client configuration - can be a single config or array of configs */\n redis?: ClientConfig<any> | ClientConfig<any>[];\n\n /** Elasticsearch client configuration - can be a single config or array of configs */\n elasticsearch?: ClientConfig<any> | ClientConfig<any>[];\n };\n\n /** General configuration options */\n config?: HealthManagerConfig;\n\n /** Logger instance for logging messages */\n logger: LoggerInstanceManager;\n\n /** Optional HTTP or HTTPS server instance to manage during shutdown */\n server?: ServerConfig;\n}\n\nexport interface RedisClient {\n ping: () => Promise<string | void>;\n}\n\n/**\n * Sequelize database interface\n */\nexport interface SequelizeClient {\n query(sql: string | { query: string; values: unknown[]; }): Promise<any>;\n}\n\n/**\n * Elasticsearch client interface\n */\nexport interface ElasticsearchClient {\n ping: () => Promise<boolean>;\n}\n\nexport interface EventsClient {\n exitHandler: () => Promise<void>;\n}\n\n/**\n * RabbitMQ client interface\n */\nexport interface RabbitMQClient {\n isConnected: () => Promise<boolean> | boolean;\n}\n\nexport const CLIENT_TYPES = {\n RABBIT: 'rabbit',\n SEQUELIZE: 'sequelize',\n REDIS: 'redis',\n ELASTIC_SEARCH: 'elasticsearch',\n EVENTS: 'events',\n} as const;\n\nexport type ClientType = typeof CLIENT_TYPES[keyof typeof CLIENT_TYPES];\n"],"mappings":"AAyJA,MAAa,EAAe,CAC1B,OAAQ,SACR,UAAW,YACX,MAAO,QACP,eAAgB,gBAChB,OAAQ,SACT"}
|