@adalo/metrics 0.1.130 → 0.1.131

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.
@@ -1 +1 @@
1
- {"version":3,"file":"healthCheckCache.d.ts","sourceRoot":"","sources":["../../src/health/healthCheckCache.js"],"names":[],"mappings":"AAOA;;;;GAIG;AACH;IACE;;;;;OAKG;IACH;QAJyB,WAAW,GAAzB,GAAG;QACc,OAAO;QACP,UAAU;OAsBrC;IAnBC,iBAA8C;IAC9C,gBACgE;IAChE,mBAAiD;IACjD,iBAA6C;IAE7C,+BAA+B;IAC/B,kBAAwB;IACxB,2BAAiC;IAG/B,qCAA4D;IAC5D,yBAA2B;IAS/B;;;;OAIG;IACH,6BAiCC;IAED;;;;;OAKG;IACH,OAHa,QAAQ,MAAM,GAAG,IAAI,CAAC,CA2DlC;IAED;;;;OAIG;IACH,YAHW,MAAM,GACJ,QAAQ,IAAI,CAAC,CAwCzB;IAED;;;OAGG;IACH,SAFa,QAAQ,IAAI,CAAC,CAyBzB;IAED;;;OAGG;IACH,oBAFa,OAAO,CAInB;CACF"}
1
+ {"version":3,"file":"healthCheckCache.d.ts","sourceRoot":"","sources":["../../src/health/healthCheckCache.js"],"names":[],"mappings":"AAOA;;;;GAIG;AACH;IACE;;;;;OAKG;IACH;QAJyB,WAAW,GAAzB,GAAG;QACc,OAAO;QACP,UAAU;OAsBrC;IAnBC,iBAA8C;IAC9C,gBACgE;IAChE,mBAA8C;IAC9C,iBAA6C;IAE7C,+BAA+B;IAC/B,kBAAwB;IACxB,2BAAiC;IAG/B,qCAA4D;IAC5D,yBAA2B;IAS/B;;;;OAIG;IACH,6BAgCC;IAED;;;;;OAKG;IACH,OAHa,QAAQ,MAAM,GAAG,IAAI,CAAC,CAsDlC;IAED;;;;OAIG;IACH,YAHW,MAAM,GACJ,QAAQ,IAAI,CAAC,CAqCzB;IAED;;;OAGG;IACH,SAFa,QAAQ,IAAI,CAAC,CAyBzB;IAED;;;OAGG;IACH,oBAFa,OAAO,CAInB;CACF"}
@@ -22,7 +22,7 @@ class HealthCheckCache {
22
22
  constructor(options = {}) {
23
23
  this.redisClient = options.redisClient || null;
24
24
  this.appName = options.appName || process.env.BUILD_APP_NAME || 'unknown-app';
25
- this.cacheTtlMs = options.cacheTtlMs ?? 60 * 1000;
25
+ this.cacheTtlMs = options.cacheTtlMs ?? 60_000;
26
26
  this.cacheKey = `healthcheck:${this.appName}`;
27
27
 
28
28
  /** In-memory fallback cache */
@@ -61,7 +61,6 @@ class HealthCheckCache {
61
61
  }
62
62
  return pong === 'PONG';
63
63
  } catch (err) {
64
- // Redis not available
65
64
  if (this._redisAvailable) {
66
65
  console.warn(`[HealthCheckCache] Redis became unavailable: ${err.message}`);
67
66
  this._redisAvailable = false;
@@ -77,7 +76,6 @@ class HealthCheckCache {
77
76
  * @throws {Error} If Redis is configured but read fails
78
77
  */
79
78
  async get() {
80
- // If Redis is configured, we MUST read from it (don't fall back to memory)
81
79
  if (this.redisClient) {
82
80
  try {
83
81
  let cachedStr;
@@ -96,7 +94,6 @@ class HealthCheckCache {
96
94
  if (cached.result && cached.timestamp) {
97
95
  const age = Date.now() - cached.timestamp;
98
96
  if (age < this.cacheTtlMs) {
99
- // Also update in-memory cache as backup
100
97
  this._memoryCache = cached.result;
101
98
  this._memoryCacheTimestamp = cached.timestamp;
102
99
  return cached.result;
@@ -106,16 +103,12 @@ class HealthCheckCache {
106
103
  console.warn(`[HealthCheckCache] Failed to parse Redis cache:`, parseErr.message);
107
104
  }
108
105
  }
109
- // No cache in Redis - return null (worker may not have run yet)
110
106
  return null;
111
107
  } catch (redisErr) {
112
- // Redis read failed - throw error so caller can return proper error format
113
108
  this._redisAvailable = false;
114
109
  throw new Error(`Redis cache read failed: ${redisErr.message}`);
115
110
  }
116
111
  }
117
-
118
- // No Redis configured - fall back to in-memory cache
119
112
  if (this._memoryCache && this._memoryCacheTimestamp) {
120
113
  const age = Date.now() - this._memoryCacheTimestamp;
121
114
  if (age < this.cacheTtlMs) {
@@ -135,12 +128,8 @@ class HealthCheckCache {
135
128
  result,
136
129
  timestamp: Date.now()
137
130
  };
138
-
139
- // Update in-memory cache
140
131
  this._memoryCache = result;
141
132
  this._memoryCacheTimestamp = cacheData.timestamp;
142
-
143
- // Try to update Redis if available
144
133
  if (await this._checkRedisAvailable()) {
145
134
  try {
146
135
  const cacheStr = JSON.stringify(cacheData);
@@ -155,7 +144,6 @@ class HealthCheckCache {
155
144
  await this.redisClient.setex(this.cacheKey, ttlSeconds, cacheStr);
156
145
  }
157
146
  } catch (redisErr) {
158
- // Redis write failed, but in-memory cache is updated
159
147
  console.warn(`[HealthCheckCache] Redis write failed (in-memory cache updated):`, redisErr.message);
160
148
  this._redisAvailable = false;
161
149
  }
@@ -1 +1 @@
1
- {"version":3,"file":"healthCheckCache.js","names":["getRedisClientType","REDIS_V4","IOREDIS","REDIS_V3","require","HealthCheckCache","constructor","options","redisClient","appName","process","env","BUILD_APP_NAME","cacheTtlMs","cacheKey","_memoryCache","_memoryCacheTimestamp","_redisClientType","_redisAvailable","console","warn","_checkRedisAvailable","pong","Promise","resolve","reject","ping","err","result","message","get","cachedStr","cached","JSON","parse","timestamp","age","Date","now","parseErr","redisErr","Error","set","cacheData","cacheStr","stringify","ttlSeconds","Math","ceil","setex","clear","del","isRedisAvailable","module","exports"],"sources":["../../src/health/healthCheckCache.js"],"sourcesContent":["const {\n getRedisClientType,\n REDIS_V4,\n IOREDIS,\n REDIS_V3,\n} = require('../redisUtils')\n\n/**\n * HealthCheckCache provides a shared cache layer for health check results.\n * It uses Redis if available for cross-process sharing, with graceful fallback\n * to in-memory cache if Redis is not configured or unavailable.\n */\nclass HealthCheckCache {\n /**\n * @param {Object} options\n * @param {any} [options.redisClient] - Redis client instance (optional)\n * @param {string} [options.appName] - Application name for cache key\n * @param {number} [options.cacheTtlMs=60000] - Cache TTL in milliseconds\n */\n constructor(options = {}) {\n this.redisClient = options.redisClient || null\n this.appName =\n options.appName || process.env.BUILD_APP_NAME || 'unknown-app'\n this.cacheTtlMs = options.cacheTtlMs ?? 60 * 1000\n this.cacheKey = `healthcheck:${this.appName}`\n\n /** In-memory fallback cache */\n this._memoryCache = null\n this._memoryCacheTimestamp = null\n\n if (this.redisClient) {\n this._redisClientType = getRedisClientType(this.redisClient)\n this._redisAvailable = true\n } else {\n this._redisAvailable = false\n console.warn(\n `[HealthCheckCache] Redis not configured for ${this.appName}, using in-memory cache only (not shared across processes)`\n )\n }\n }\n\n /**\n * Checks if Redis is available and working.\n * @returns {Promise<boolean>}\n * @private\n */\n async _checkRedisAvailable() {\n if (!this.redisClient || !this._redisAvailable) {\n return false\n }\n\n try {\n let pong\n if (this._redisClientType === REDIS_V3) {\n pong = await new Promise((resolve, reject) => {\n this.redisClient.ping((err, result) => {\n if (err) reject(err)\n else resolve(result)\n })\n })\n } else if (\n this._redisClientType === REDIS_V4 ||\n this._redisClientType === IOREDIS\n ) {\n pong = await this.redisClient.ping()\n } else {\n return false\n }\n return pong === 'PONG'\n } catch (err) {\n // Redis not available\n if (this._redisAvailable) {\n console.warn(\n `[HealthCheckCache] Redis became unavailable: ${err.message}`\n )\n this._redisAvailable = false\n }\n return false\n }\n }\n\n /**\n * Gets cached health check result from Redis (if available) or in-memory cache.\n * Throws error if Redis is configured but read fails (so caller can return proper error format).\n * @returns {Promise<Object | null>} Cached result or null\n * @throws {Error} If Redis is configured but read fails\n */\n async get() {\n // If Redis is configured, we MUST read from it (don't fall back to memory)\n if (this.redisClient) {\n try {\n let cachedStr\n if (this._redisClientType === REDIS_V3) {\n cachedStr = await new Promise((resolve, reject) => {\n this.redisClient.get(this.cacheKey, (err, result) => {\n if (err) reject(err)\n else resolve(result)\n })\n })\n } else if (\n this._redisClientType === REDIS_V4 ||\n this._redisClientType === IOREDIS\n ) {\n cachedStr = await this.redisClient.get(this.cacheKey)\n }\n\n if (cachedStr) {\n try {\n const cached = JSON.parse(cachedStr)\n if (cached.result && cached.timestamp) {\n const age = Date.now() - cached.timestamp\n if (age < this.cacheTtlMs) {\n // Also update in-memory cache as backup\n this._memoryCache = cached.result\n this._memoryCacheTimestamp = cached.timestamp\n return cached.result\n }\n }\n } catch (parseErr) {\n console.warn(\n `[HealthCheckCache] Failed to parse Redis cache:`,\n parseErr.message\n )\n }\n }\n // No cache in Redis - return null (worker may not have run yet)\n return null\n } catch (redisErr) {\n // Redis read failed - throw error so caller can return proper error format\n this._redisAvailable = false\n throw new Error(`Redis cache read failed: ${redisErr.message}`)\n }\n }\n\n // No Redis configured - fall back to in-memory cache\n if (this._memoryCache && this._memoryCacheTimestamp) {\n const age = Date.now() - this._memoryCacheTimestamp\n if (age < this.cacheTtlMs) {\n return this._memoryCache\n }\n }\n\n return null\n }\n\n /**\n * Sets cached health check result in Redis (if available) and in-memory.\n * @param {Object} result - Health check result to cache\n * @returns {Promise<void>}\n */\n async set(result) {\n const cacheData = {\n result,\n timestamp: Date.now(),\n }\n\n // Update in-memory cache\n this._memoryCache = result\n this._memoryCacheTimestamp = cacheData.timestamp\n\n // Try to update Redis if available\n if (await this._checkRedisAvailable()) {\n try {\n const cacheStr = JSON.stringify(cacheData)\n const ttlSeconds = Math.ceil(this.cacheTtlMs / 1000) + 10\n\n if (this._redisClientType === REDIS_V3) {\n await new Promise((resolve, reject) => {\n this.redisClient.setex(this.cacheKey, ttlSeconds, cacheStr, err => {\n if (err) reject(err)\n else resolve()\n })\n })\n } else if (\n this._redisClientType === REDIS_V4 ||\n this._redisClientType === IOREDIS\n ) {\n await this.redisClient.setex(this.cacheKey, ttlSeconds, cacheStr)\n }\n } catch (redisErr) {\n // Redis write failed, but in-memory cache is updated\n console.warn(\n `[HealthCheckCache] Redis write failed (in-memory cache updated):`,\n redisErr.message\n )\n this._redisAvailable = false\n }\n }\n }\n\n /**\n * Clears the cache (both Redis and in-memory).\n * @returns {Promise<void>}\n */\n async clear() {\n this._memoryCache = null\n this._memoryCacheTimestamp = null\n\n if (await this._checkRedisAvailable()) {\n try {\n if (this._redisClientType === REDIS_V3) {\n await new Promise((resolve, reject) => {\n this.redisClient.del(this.cacheKey, err => {\n if (err) reject(err)\n else resolve()\n })\n })\n } else if (\n this._redisClientType === REDIS_V4 ||\n this._redisClientType === IOREDIS\n ) {\n await this.redisClient.del(this.cacheKey)\n }\n } catch (redisErr) {\n console.warn(`[HealthCheckCache] Redis clear failed:`, redisErr.message)\n }\n }\n }\n\n /**\n * Checks if Redis is configured and available.\n * @returns {boolean}\n */\n isRedisAvailable() {\n return this._redisAvailable && this.redisClient !== null\n }\n}\n\nmodule.exports = { HealthCheckCache }\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"healthCheckCache.js","names":["getRedisClientType","REDIS_V4","IOREDIS","REDIS_V3","require","HealthCheckCache","constructor","options","redisClient","appName","process","env","BUILD_APP_NAME","cacheTtlMs","cacheKey","_memoryCache","_memoryCacheTimestamp","_redisClientType","_redisAvailable","console","warn","_checkRedisAvailable","pong","Promise","resolve","reject","ping","err","result","message","get","cachedStr","cached","JSON","parse","timestamp","age","Date","now","parseErr","redisErr","Error","set","cacheData","cacheStr","stringify","ttlSeconds","Math","ceil","setex","clear","del","isRedisAvailable","module","exports"],"sources":["../../src/health/healthCheckCache.js"],"sourcesContent":["const {\n getRedisClientType,\n REDIS_V4,\n IOREDIS,\n REDIS_V3,\n} = require('../redisUtils')\n\n/**\n * HealthCheckCache provides a shared cache layer for health check results.\n * It uses Redis if available for cross-process sharing, with graceful fallback\n * to in-memory cache if Redis is not configured or unavailable.\n */\nclass HealthCheckCache {\n /**\n * @param {Object} options\n * @param {any} [options.redisClient] - Redis client instance (optional)\n * @param {string} [options.appName] - Application name for cache key\n * @param {number} [options.cacheTtlMs=60000] - Cache TTL in milliseconds\n */\n constructor(options = {}) {\n this.redisClient = options.redisClient || null\n this.appName =\n options.appName || process.env.BUILD_APP_NAME || 'unknown-app'\n this.cacheTtlMs = options.cacheTtlMs ?? 60_000\n this.cacheKey = `healthcheck:${this.appName}`\n\n /** In-memory fallback cache */\n this._memoryCache = null\n this._memoryCacheTimestamp = null\n\n if (this.redisClient) {\n this._redisClientType = getRedisClientType(this.redisClient)\n this._redisAvailable = true\n } else {\n this._redisAvailable = false\n console.warn(\n `[HealthCheckCache] Redis not configured for ${this.appName}, using in-memory cache only (not shared across processes)`\n )\n }\n }\n\n /**\n * Checks if Redis is available and working.\n * @returns {Promise<boolean>}\n * @private\n */\n async _checkRedisAvailable() {\n if (!this.redisClient || !this._redisAvailable) {\n return false\n }\n\n try {\n let pong\n if (this._redisClientType === REDIS_V3) {\n pong = await new Promise((resolve, reject) => {\n this.redisClient.ping((err, result) => {\n if (err) reject(err)\n else resolve(result)\n })\n })\n } else if (\n this._redisClientType === REDIS_V4 ||\n this._redisClientType === IOREDIS\n ) {\n pong = await this.redisClient.ping()\n } else {\n return false\n }\n return pong === 'PONG'\n } catch (err) {\n if (this._redisAvailable) {\n console.warn(\n `[HealthCheckCache] Redis became unavailable: ${err.message}`\n )\n this._redisAvailable = false\n }\n return false\n }\n }\n\n /**\n * Gets cached health check result from Redis (if available) or in-memory cache.\n * Throws error if Redis is configured but read fails (so caller can return proper error format).\n * @returns {Promise<Object | null>} Cached result or null\n * @throws {Error} If Redis is configured but read fails\n */\n async get() {\n if (this.redisClient) {\n try {\n let cachedStr\n if (this._redisClientType === REDIS_V3) {\n cachedStr = await new Promise((resolve, reject) => {\n this.redisClient.get(this.cacheKey, (err, result) => {\n if (err) reject(err)\n else resolve(result)\n })\n })\n } else if (\n this._redisClientType === REDIS_V4 ||\n this._redisClientType === IOREDIS\n ) {\n cachedStr = await this.redisClient.get(this.cacheKey)\n }\n\n if (cachedStr) {\n try {\n const cached = JSON.parse(cachedStr)\n if (cached.result && cached.timestamp) {\n const age = Date.now() - cached.timestamp\n if (age < this.cacheTtlMs) {\n this._memoryCache = cached.result\n this._memoryCacheTimestamp = cached.timestamp\n return cached.result\n }\n }\n } catch (parseErr) {\n console.warn(\n `[HealthCheckCache] Failed to parse Redis cache:`,\n parseErr.message\n )\n }\n }\n return null\n } catch (redisErr) {\n this._redisAvailable = false\n throw new Error(`Redis cache read failed: ${redisErr.message}`)\n }\n }\n\n if (this._memoryCache && this._memoryCacheTimestamp) {\n const age = Date.now() - this._memoryCacheTimestamp\n if (age < this.cacheTtlMs) {\n return this._memoryCache\n }\n }\n\n return null\n }\n\n /**\n * Sets cached health check result in Redis (if available) and in-memory.\n * @param {Object} result - Health check result to cache\n * @returns {Promise<void>}\n */\n async set(result) {\n const cacheData = {\n result,\n timestamp: Date.now(),\n }\n\n this._memoryCache = result\n this._memoryCacheTimestamp = cacheData.timestamp\n\n if (await this._checkRedisAvailable()) {\n try {\n const cacheStr = JSON.stringify(cacheData)\n const ttlSeconds = Math.ceil(this.cacheTtlMs / 1000) + 10\n\n if (this._redisClientType === REDIS_V3) {\n await new Promise((resolve, reject) => {\n this.redisClient.setex(this.cacheKey, ttlSeconds, cacheStr, err => {\n if (err) reject(err)\n else resolve()\n })\n })\n } else if (\n this._redisClientType === REDIS_V4 ||\n this._redisClientType === IOREDIS\n ) {\n await this.redisClient.setex(this.cacheKey, ttlSeconds, cacheStr)\n }\n } catch (redisErr) {\n console.warn(\n `[HealthCheckCache] Redis write failed (in-memory cache updated):`,\n redisErr.message\n )\n this._redisAvailable = false\n }\n }\n }\n\n /**\n * Clears the cache (both Redis and in-memory).\n * @returns {Promise<void>}\n */\n async clear() {\n this._memoryCache = null\n this._memoryCacheTimestamp = null\n\n if (await this._checkRedisAvailable()) {\n try {\n if (this._redisClientType === REDIS_V3) {\n await new Promise((resolve, reject) => {\n this.redisClient.del(this.cacheKey, err => {\n if (err) reject(err)\n else resolve()\n })\n })\n } else if (\n this._redisClientType === REDIS_V4 ||\n this._redisClientType === IOREDIS\n ) {\n await this.redisClient.del(this.cacheKey)\n }\n } catch (redisErr) {\n console.warn(`[HealthCheckCache] Redis clear failed:`, redisErr.message)\n }\n }\n }\n\n /**\n * Checks if Redis is configured and available.\n * @returns {boolean}\n */\n isRedisAvailable() {\n return this._redisAvailable && this.redisClient !== null\n }\n}\n\nmodule.exports = { HealthCheckCache }\n"],"mappings":"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","ignoreList":[]}
@@ -1,266 +1,140 @@
1
- export type HealthStatus = 'healthy' | 'unhealthy' | 'degraded';
2
- export type ComponentHealth = {
3
- /**
4
- * - Component health status
5
- */
6
- status: HealthStatus;
7
- /**
8
- * - Error message if status is unhealthy
9
- */
10
- error?: string | undefined;
11
- /**
12
- * - Optional status message (deprecated, use error)
13
- */
14
- message?: string | undefined;
15
- /**
16
- * - Connection latency in milliseconds
17
- */
18
- latencyMs?: number | undefined;
19
- };
20
- export type DatabaseClusterHealth = {
21
- /**
22
- * - Overall databases status
23
- */
24
- status: HealthStatus;
25
- /**
26
- * - Individual cluster health
27
- */
28
- clusters: {
29
- [x: string]: ComponentHealth;
30
- };
31
- };
32
- export type HealthCheckResult = {
33
- /**
34
- * - Overall health status
35
- */
36
- status: HealthStatus;
37
- /**
38
- * - ISO timestamp of the check
39
- */
40
- timestamp: string;
41
- /**
42
- * - Individual service health checks
43
- */
44
- checks: {
45
- [x: string]: ComponentHealth | DatabaseClusterHealth;
46
- };
47
- /**
48
- * - Top-level error messages (not related to specific services)
49
- */
50
- errors?: string[] | undefined;
51
- };
52
- export type CachedHealthResult = {
53
- /**
54
- * - The cached health check result
55
- */
56
- result: HealthCheckResult;
57
- /**
58
- * - Unix timestamp when cached
59
- */
60
- timestamp: number;
61
- };
62
- export type DatabaseConfig = {
63
- /**
64
- * - Database/cluster name
65
- */
1
+ export type HealthResource = {
66
2
  name: string;
67
- /**
68
- * - Connection URL
69
- */
70
- url: string;
3
+ url?: string;
4
+ } | {
5
+ name: string;
6
+ client: any;
71
7
  };
72
8
  /**
73
- * @typedef {'healthy' | 'unhealthy' | 'degraded'} HealthStatus
74
- */
75
- /**
76
- * @typedef {Object} ComponentHealth
77
- * @property {HealthStatus} status - Component health status
78
- * @property {string} [error] - Error message if status is unhealthy
79
- * @property {string} [message] - Optional status message (deprecated, use error)
80
- * @property {number} [latencyMs] - Connection latency in milliseconds
81
- */
82
- /**
83
- * @typedef {Object} DatabaseClusterHealth
84
- * @property {HealthStatus} status - Overall databases status
85
- * @property {Object<string, ComponentHealth>} clusters - Individual cluster health
86
- */
87
- /**
88
- * @typedef {Object} HealthCheckResult
89
- * @property {HealthStatus} status - Overall health status
90
- * @property {string} timestamp - ISO timestamp of the check
91
- * @property {Object<string, ComponentHealth | DatabaseClusterHealth>} checks - Individual service health checks
92
- * @property {string[]} [errors] - Top-level error messages (not related to specific services)
93
- */
94
- /**
95
- * @typedef {Object} CachedHealthResult
96
- * @property {HealthCheckResult} result - The cached health check result
97
- * @property {number} timestamp - Unix timestamp when cached
98
- */
99
- /**
100
- * @typedef {Object} DatabaseConfig
101
- * @property {string} name - Database/cluster name
102
- * @property {string} url - Connection URL
103
- */
104
- /**
105
- * HealthCheckClient provides a health check middleware for external monitoring services
106
- * like BetterStack. It validates database and Redis connections with rate limiting
107
- * to prevent excessive load on backend services.
108
- *
109
- * Features:
110
- * - Multi-cluster DB validation (PostgreSQL)
111
- * - Redis connection validation (supports ioredis, node-redis v3/v4)
112
- * - Result caching (default: 60 seconds) to prevent overloading services
113
- * - Express middleware support
114
- * - BetterStack-compatible JSON response format
9
+ * @typedef {{ name: string, url?: string } | { name: string, client: any }} HealthResource
115
10
  */
116
11
  export class HealthCheckClient {
117
12
  /**
118
13
  * @param {Object} options
119
- * @param {string} [options.databaseUrl] - Main PostgreSQL connection URL
120
- * @param {string} [options.databaseName='main'] - Name for the main database
121
- * @param {Object<string, string>} [options.additionalDatabaseUrls] - Additional DB clusters (name -> URL)
122
- * @param {any} [options.redisClient] - Redis client instance (ioredis or node-redis) - used for cache
123
- * @param {boolean} [options.includeRedisCheck=false] - Include Redis health check in results (for backend)
124
- * @param {number} [options.cacheTtlMs=60000] - Cache TTL in milliseconds (default: 60s)
125
- * @param {string} [options.appName] - Application name for logging
14
+ * @param {HealthResource[]} options.resources - Must include Redis resource with client
15
+ * @param {number} [options.cacheTtlMs]
16
+ * @param {Object} [options.config]
17
+ * @param {string} [options.appName]
126
18
  */
127
19
  constructor(options?: {
128
- databaseUrl?: string | undefined;
129
- databaseName?: string | undefined;
130
- additionalDatabaseUrls?: {
131
- [x: string]: string;
132
- } | undefined;
133
- redisClient?: any;
134
- includeRedisCheck?: boolean | undefined;
20
+ resources: HealthResource[];
135
21
  cacheTtlMs?: number | undefined;
22
+ config?: Object | undefined;
136
23
  appName?: string | undefined;
137
24
  });
138
- redisClient: any;
139
- includeRedisCheck: boolean;
25
+ healthConfig: {
26
+ constructor?: Function | undefined;
27
+ toString?: (() => string) | undefined;
28
+ toLocaleString?: (() => string) | undefined;
29
+ valueOf?: (() => Object) | undefined;
30
+ hasOwnProperty?: ((v: PropertyKey) => boolean) | undefined;
31
+ isPrototypeOf?: ((v: Object) => boolean) | undefined;
32
+ propertyIsEnumerable?: ((v: PropertyKey) => boolean) | undefined;
33
+ cacheTtlMs: number;
34
+ checkIntervalMs: number;
35
+ staleThresholdMs: number;
36
+ checkTimeoutMs: number;
37
+ };
140
38
  cacheTtlMs: number;
141
39
  appName: string;
142
40
  prefixLogs: string;
143
- /** @type {CachedHealthResult | null} */
144
- _cachedResult: CachedHealthResult | null;
145
- /** @type {Promise<HealthCheckResult> | null} */
146
- _refreshPromise: Promise<HealthCheckResult> | null;
147
- /** @type {Map<string, Pool>} */
148
- _databasePools: Map<string, Pool>;
149
- /** @type {DatabaseConfig | null} */
150
- _mainDatabaseConfig: DatabaseConfig | null;
151
- /** @type {DatabaseConfig[]} */
152
- _clusterConfigs: DatabaseConfig[];
41
+ _cachedResult: {
42
+ result: {
43
+ status: string;
44
+ lastCheckAt: number;
45
+ resources: {};
46
+ isStale: boolean;
47
+ config: {
48
+ constructor?: Function | undefined;
49
+ toString?: (() => string) | undefined;
50
+ toLocaleString?: (() => string) | undefined;
51
+ valueOf?: (() => Object) | undefined;
52
+ hasOwnProperty?: ((v: PropertyKey) => boolean) | undefined;
53
+ isPrototypeOf?: ((v: Object) => boolean) | undefined;
54
+ propertyIsEnumerable?: ((v: PropertyKey) => boolean) | undefined;
55
+ cacheTtlMs: number;
56
+ checkIntervalMs: number;
57
+ staleThresholdMs: number;
58
+ checkTimeoutMs: number;
59
+ };
60
+ };
61
+ timestamp: number;
62
+ } | null;
63
+ _refreshPromise: any;
64
+ _databasePools: Map<any, any>;
65
+ /** @type {HealthResource[]} */
66
+ _resources: HealthResource[];
153
67
  _redisClientType: string | undefined;
154
68
  _cache: HealthCheckCache;
155
- /**
156
- * Initialize database configurations from options.
157
- * @param {Object} options - Constructor options
158
- * @private
159
- */
160
- private _initDatabases;
161
- /**
162
- * Get or create a database pool for a given config.
163
- * @param {DatabaseConfig} config - Database configuration
164
- * @returns {Pool}
165
- * @private
166
- */
167
- private _getPool;
168
- /**
169
- * Checks if cached result is still valid based on TTL.
170
- * @returns {boolean}
171
- * @private
172
- */
173
- private _isCacheValid;
174
- /**
175
- * Tests a single database cluster connectivity.
176
- * @param {DatabaseConfig} config - Database configuration
177
- * @returns {Promise<ComponentHealth>}
178
- * @private
179
- */
180
- private _checkSingleDatabase;
181
- /**
182
- * Tests all PostgreSQL databases (main + clusters) in parallel.
183
- * @returns {Promise<Object | null>} Database health with optional clusters
184
- * @private
185
- */
186
- private _checkAllDatabases;
187
- /**
188
- * Tests Redis connectivity using PING command.
189
- * @returns {Promise<ComponentHealth>}
190
- * @private
191
- */
192
- private _checkRedis;
193
- /**
194
- * Performs a full health check on all configured components.
195
- * Results are cached for the configured TTL to prevent excessive load.
196
- * Uses a mutex pattern to prevent concurrent health checks when cache expires.
197
- * If cache is expired but a refresh is in progress, returns stale cache (if available).
198
- *
199
- * @returns {Promise<HealthCheckResult>}
200
- */
201
- performHealthCheck(): Promise<HealthCheckResult>;
202
- /**
203
- * Internal method that actually performs the health check.
204
- * This is separated to allow the mutex pattern in performHealthCheck.
205
- * Only checks database - Redis is used only for cache, not health check.
206
- *
207
- * @returns {Promise<HealthCheckResult>}
208
- * @private
209
- */
210
- private _performHealthCheckInternal;
211
- /**
212
- * Gets cached result from shared cache (Redis if available, otherwise in-memory).
213
- * Returns null if no cache is available. This is used by endpoints to read-only access.
214
- * If Redis fails, returns error result with proper format.
215
- *
216
- * @returns {Promise<HealthCheckResult | null>} Cached result, error result if Redis fails, or null if not available
217
- */
218
- getCachedResult(): Promise<HealthCheckResult | null>;
219
- /**
220
- * Forces a refresh of the health check cache.
221
- * This is used by background workers to periodically update the cache.
222
- * Updates shared cache (Redis if available, otherwise in-memory).
223
- *
224
- * @returns {Promise<HealthCheckResult>}
225
- */
226
- refreshCache(): Promise<HealthCheckResult>;
227
- /**
228
- * Clears the cached health check result, forcing the next check to be fresh.
229
- */
69
+ _getRedisClientForCache(): any;
70
+ _getPool(name: any, url: any): any;
71
+ _isCacheValid(): boolean;
72
+ _checkDatabase(resource: any): Promise<{
73
+ status: string;
74
+ error: string;
75
+ } | {
76
+ status: string;
77
+ error?: undefined;
78
+ }>;
79
+ _checkRedis(resource: any): Promise<{
80
+ status: string;
81
+ error?: undefined;
82
+ } | {
83
+ status: string;
84
+ error: string;
85
+ }>;
86
+ _performHealthCheckInternal(): Promise<{
87
+ status: string;
88
+ lastCheckAt: number;
89
+ resources: {};
90
+ isStale: boolean;
91
+ config: {
92
+ constructor?: Function | undefined;
93
+ toString?: (() => string) | undefined;
94
+ toLocaleString?: (() => string) | undefined;
95
+ valueOf?: (() => Object) | undefined;
96
+ hasOwnProperty?: ((v: PropertyKey) => boolean) | undefined;
97
+ isPrototypeOf?: ((v: Object) => boolean) | undefined;
98
+ propertyIsEnumerable?: ((v: PropertyKey) => boolean) | undefined;
99
+ cacheTtlMs: number;
100
+ checkIntervalMs: number;
101
+ staleThresholdMs: number;
102
+ checkTimeoutMs: number;
103
+ };
104
+ }>;
105
+ _formatResult(result: any, cached?: boolean): any;
106
+ performHealthCheck(): Promise<any>;
107
+ getCachedResult(): Promise<any>;
108
+ refreshCache(): Promise<{
109
+ status: string;
110
+ lastCheckAt: number;
111
+ resources: {};
112
+ isStale: boolean;
113
+ config: {
114
+ constructor?: Function | undefined;
115
+ toString?: (() => string) | undefined;
116
+ toLocaleString?: (() => string) | undefined;
117
+ valueOf?: (() => Object) | undefined;
118
+ hasOwnProperty?: ((v: PropertyKey) => boolean) | undefined;
119
+ isPrototypeOf?: ((v: Object) => boolean) | undefined;
120
+ propertyIsEnumerable?: ((v: PropertyKey) => boolean) | undefined;
121
+ cacheTtlMs: number;
122
+ checkIntervalMs: number;
123
+ staleThresholdMs: number;
124
+ checkTimeoutMs: number;
125
+ };
126
+ }>;
230
127
  clearCache(): void;
231
- /**
232
- * Builds a list of error messages from health check result.
233
- * All error messages are sanitized to remove sensitive information.
234
- * @param {HealthCheckResult} result - Health check result
235
- * @returns {string[]} Array of sanitized error messages
236
- * @private
237
- */
238
- private _getErrorMessages;
239
- /**
240
- * Express middleware handler for health check endpoint.
241
- * Returns 200 for healthy/degraded, 503 for unhealthy.
242
- * Response includes errors array when status is not healthy.
243
- * All sensitive data (passwords, connection strings, etc.) is masked.
244
- *
245
- * This handler only reads from cache and never triggers database queries.
246
- * Use a background worker to periodically refresh the cache.
247
- *
248
- * @returns {(req: any, res: any) => Promise<void>} Express request handler
249
- */
250
128
  healthHandler(): (req: any, res: any) => Promise<void>;
251
- /**
252
- * Register health check endpoint on an Express app.
253
- *
254
- * @param {import('express').Application} app - Express application
255
- * @param {string} [path='/health'] - Path for the health endpoint
256
- */
257
- registerHealthEndpoint(app: any, path?: string | undefined): void;
258
- /**
259
- * Cleanup resources (database pools).
260
- * @returns {Promise<void>}
261
- */
129
+ registerHealthEndpoint(app: any, path?: string): void;
262
130
  cleanup(): Promise<void>;
263
131
  }
264
- import { Pool } from "pg";
132
+ /** @type {{ cacheTtlMs: number, checkIntervalMs: number, staleThresholdMs: number, checkTimeoutMs: number }} */
133
+ export const DEFAULT_HEALTH_CONFIG: {
134
+ cacheTtlMs: number;
135
+ checkIntervalMs: number;
136
+ staleThresholdMs: number;
137
+ checkTimeoutMs: number;
138
+ };
265
139
  import { HealthCheckCache } from "./healthCheckCache";
266
140
  //# sourceMappingURL=healthCheckClient.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"healthCheckClient.d.ts","sourceRoot":"","sources":["../../src/health/healthCheckClient.js"],"names":[],"mappings":"2BAoEa,SAAS,GAAG,WAAW,GAAG,UAAU;;;;;YAKnC,YAAY;;;;;;;;;;;;;;;;;;YAQZ,YAAY;;;;;YACL,MAAM,GAAE,eAAe;;;;;;;YAK9B,YAAY;;;;eACZ,MAAM;;;;;YACC,MAAM,GAAE,eAAe,GAAG,qBAAqB;;;;;;;;;;;YAMtD,iBAAiB;;;;eACjB,MAAM;;;;;;UAKN,MAAM;;;;SACN,MAAM;;AAnCpB;;GAEG;AAEH;;;;;;GAMG;AAEH;;;;GAIG;AAEH;;;;;;GAMG;AAEH;;;;GAIG;AAEH;;;;GAIG;AAEH;;;;;;;;;;;GAWG;AACH;IACE;;;;;;;;;OASG;IACH;QAR4B,WAAW;QACX,YAAY;QACI,sBAAsB;;;QACzC,WAAW,GAAzB,GAAG;QACe,iBAAiB;QAClB,UAAU;QACV,OAAO;OAqClC;IAlCC,iBAA8C;IAC9C,2BAA2D;IAC3D,mBAAiE;IACjE,gBACgE;IAEhE,mBAAmD;IAEnD,wCAAwC;IACxC,eADW,kBAAkB,GAAG,IAAI,CACX;IAEzB,gDAAgD;IAChD,iBADW,QAAQ,iBAAiB,CAAC,GAAG,IAAI,CACjB;IAE3B,gCAAgC;IAChC,gBADW,IAAI,MAAM,EAAE,IAAI,CAAC,CACG;IAE/B,oCAAoC;IACpC,qBADW,cAAc,GAAG,IAAI,CACD;IAE/B,+BAA+B;IAC/B,iBADW,cAAc,EAAE,CACF;IAKvB,qCAA4D;IAG9D,yBAIE;IAGJ;;;;OAIG;IACH,uBAcC;IAED;;;;;OAKG;IACH,iBAaC;IAED;;;;OAIG;IACH,sBAGC;IAED;;;;;OAKG;IACH,6BAiBC;IAED;;;;OAIG;IACH,2BAsDC;IAED;;;;OAIG;IACH,oBA6CC;IAED;;;;;;;OAOG;IACH,sBAFa,QAAQ,iBAAiB,CAAC,CAqCtC;IAED;;;;;;;OAOG;IACH,oCAoCC;IAED;;;;;;OAMG;IACH,mBAFa,QAAQ,iBAAiB,GAAG,IAAI,CAAC,CA0B7C;IAED;;;;;;OAMG;IACH,gBAFa,QAAQ,iBAAiB,CAAC,CAOtC;IAED;;OAEG;IACH,mBAGC;IAED;;;;;;OAMG;IACH,0BAkCC;IAED;;;;;;;;;;OAUG;IACH,uBAFmB,GAAG,OAAO,GAAG,KAAK,QAAQ,IAAI,CAAC,CAwDjD;IAED;;;;;OAKG;IACH,kEAGC;IAED;;;OAGG;IACH,WAFa,QAAQ,IAAI,CAAC,CAczB;CACF"}
1
+ {"version":3,"file":"healthCheckClient.d.ts","sourceRoot":"","sources":["../../src/health/healthCheckClient.js"],"names":[],"mappings":"6BA6Da;IAAE,MAAM,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,MAAM,MAAM,CAAC;IAAC,MAAM,EAAE,GAAG,CAAA;CAAE;AAD3E;;GAEG;AACH;IACE;;;;;;OAMG;IACH;QALqC,SAAS,EAAnC,cAAc,EAAE;QACC,UAAU;QACV,MAAM;QACN,OAAO;OA8BlC;IA3BC;;;;;;;;;;;;MAAmE;IAInE,mBAA8C;IAC9C,gBACgE;IAEhE,mBAAmD;IAEnD;;;;;;;;;;;;;;;;;;;;;aAAyB;IACzB,qBAA2B;IAC3B,8BAA+B;IAE/B,+BAA+B;IAC/B,YADW,cAAc,EAAE,CACc;IAIvC,qCAAuD;IAGzD,yBAIE;IAGJ,+BAGC;IAED,mCAaC;IAED,yBAGC;IAED;;;;;;OAiBC;IAED;;;;;;OA0BC;IAED;;;;;;;;;;;;;;;;;;OAiCC;IAED,kDAWC;IAED,mCA2BC;IAED,gCAkBC;IAED;;;;;;;;;;;;;;;;;;OAIC;IAED,mBAGC;IAED,uDA0CC;IAED,sDAGC;IAED,yBASC;CACF;AA3UD,gHAAgH;AAChH,oCADW;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,eAAe,EAAE,MAAM,CAAC;IAAC,gBAAgB,EAAE,MAAM,CAAC;IAAC,cAAc,EAAE,MAAM,CAAA;CAAE,CAM3G"}