proactive-deps
Version:
A library for managing proactive dependency checks in Node.js applications.
118 lines (117 loc) • 5.36 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.DependencyMonitor = void 0;
const cache_manager_1 = require("cache-manager");
const constants_1 = require("./constants");
const format_check_result_1 = __importDefault(require("./lib/format-check-result"));
const format_prometheus_metrics_1 = __importDefault(require("./lib/format-prometheus-metrics"));
/**
* DependencyMonitor is a class that monitors the status of various dependencies
* (e.g., databases, APIs) and provides methods to check their health and latency.
* It uses a cache to store the results of the checks and can be configured
* to refresh the cache at specified intervals.
* It also provides a method to get Prometheus metrics for the monitored dependencies.
* @class DependencyMonitor
*/
class DependencyMonitor {
/**
* Creates an instance of DependencyMonitor.
* @param {DependencyMonitorOptions} [options] - Optional configuration options for the monitor.
* @default { cacheDurationMs: 60000, refreshThresholdMs: 5000, checkIntervalMs: 15000 }
* @example
* const monitor = new DependencyMonitor({
* cacheDurationMs: 60000, // Cache duration of 1 minute
* refreshThresholdMs: 5000, // Refresh threshold of 5 seconds
* checkIntervalMs: 15000, // Check interval of 15 seconds
* });
*/
constructor(options = {}) {
this._dependencies = [];
this._dependencyCheckInterval = null;
this._refreshThresholdMs = constants_1.DEFAULT_REFRESH_THRESHOLD_MS;
this._cacheDurationMs = constants_1.DEFAULT_CACHE_DURATION_MS;
this._checkIntervalMs = constants_1.DEFAULT_CHECK_INTERVAL_MS;
this.checkIntervalStarted = false;
this._cacheDurationMs =
options.cacheDurationMs || constants_1.DEFAULT_CACHE_DURATION_MS;
this._refreshThresholdMs =
options.refreshThresholdMs || constants_1.DEFAULT_REFRESH_THRESHOLD_MS;
this._checkIntervalMs =
options.checkIntervalMs || constants_1.DEFAULT_CHECK_INTERVAL_MS;
this._cache = (0, cache_manager_1.createCache)({
ttl: this._cacheDurationMs,
refreshThreshold: this._refreshThresholdMs,
});
}
startDependencyCheckInterval() {
this.checkIntervalStarted = true;
if (this._dependencyCheckInterval) {
clearInterval(this._dependencyCheckInterval);
}
this._getAllDependenciesStatus(); // Initial check
this._dependencyCheckInterval = setInterval(this._getAllDependenciesStatus.bind(this), this._checkIntervalMs);
this._dependencyCheckInterval.unref(); // Allow the process to exit if this is the only thing running
}
stopDependencyCheckInterval() {
this.checkIntervalStarted = false;
if (this._dependencyCheckInterval) {
clearInterval(this._dependencyCheckInterval);
this._dependencyCheckInterval = null;
}
}
register(dependency) {
this._dependencies.push(dependency);
}
async _getDependencyStatus(dependency) {
try {
return await this._cache.wrap(dependency.name, async () => {
if (dependency.skip) {
return (0, format_check_result_1.default)(dependency, constants_1.SUCCESS_STATUS_CODE, 0, true);
}
const start = Date.now();
const checkResults = await dependency.check();
const latencyMs = Date.now() - start;
return (0, format_check_result_1.default)(dependency, checkResults, latencyMs);
}, dependency.cacheDurationMs || this._cacheDurationMs, dependency.refreshThresholdMs || this._refreshThresholdMs);
}
catch (error) {
const status = (0, format_check_result_1.default)(dependency, {
code: constants_1.ERROR_STATUS_CODE,
error: error,
errorMessage: `Error checking dependency ${dependency.name}`,
});
await this._cache.set(dependency.name, status, dependency.cacheDurationMs);
return status;
}
}
async _getAllDependenciesStatus() {
const checkPromises = this._dependencies.map(async (dep) => this._getDependencyStatus(dep));
// Run all checks concurrently
return await Promise.all(checkPromises);
}
async getStatus(dependencyName) {
const cacheKey = dependencyName;
const cachedValue = await this._cache.get(cacheKey);
if (cachedValue) {
return cachedValue;
}
else {
const dependency = this._dependencies.find((dep) => dep.name === dependencyName);
if (dependency) {
return await this._getDependencyStatus(dependency);
}
throw new Error(`Dependency ${dependencyName} not found`);
}
}
async getAllStatuses() {
return await this._getAllDependenciesStatus();
}
async getPrometheusMetrics() {
const statuses = await this._getAllDependenciesStatus();
return (0, format_prometheus_metrics_1.default)(statuses);
}
}
exports.DependencyMonitor = DependencyMonitor;