feat(health-check): introduce health probe gap configuration and enhance health check logic
Added `healthProbeGapMs` configuration to control the minimum pause between probes to different physical targets. Updated health check service to utilize this configuration, ensuring efficient probing without overwhelming the targets. Enhanced the `runAllChecks` function to group probes by physical IP and implement the new gap logic. Updated related tests to validate the new functionality.
This commit is contained in:
Vendored
+44
-1
File diff suppressed because one or more lines are too long
Vendored
+41
-1
@@ -194,6 +194,9 @@ var appSettings = sqliteTable("app_settings", {
|
||||
mode: "boolean"
|
||||
}).notNull().default(false),
|
||||
vps_tracker_last_sync_at: text("vps_tracker_last_sync_at"),
|
||||
show_quick_actions: integer("show_quick_actions", {
|
||||
mode: "boolean"
|
||||
}).notNull().default(true),
|
||||
created_at: text("created_at").notNull().default(sql`datetime('now')`),
|
||||
updated_at: text("updated_at").notNull().default(sql`datetime('now')`)
|
||||
});
|
||||
@@ -345,6 +348,14 @@ var DEFAULT_APP_SWITCHER = {
|
||||
url: "http://192.168.100.67:6363",
|
||||
icon: "cloud",
|
||||
shortcut: "\u23182"
|
||||
},
|
||||
{
|
||||
id: "evobgp",
|
||||
name: "EvoBGP",
|
||||
subtitle: "BGP \u043C\u0430\u0440\u0448\u0440\u0443\u0442\u0438\u0437\u0430\u0446\u0438\u044F",
|
||||
url: "http://192.168.100.67:3000",
|
||||
icon: "globe",
|
||||
shortcut: "\u23183"
|
||||
}
|
||||
]
|
||||
};
|
||||
@@ -365,7 +376,8 @@ function toDto(row) {
|
||||
row.vps_tracker_integration_token?.trim()
|
||||
),
|
||||
vpsTrackerSyncEnabled: Boolean(row.vps_tracker_sync_enabled),
|
||||
vpsTrackerLastSyncAt: row.vps_tracker_last_sync_at
|
||||
vpsTrackerLastSyncAt: row.vps_tracker_last_sync_at,
|
||||
showQuickActions: row.show_quick_actions == null ? true : Boolean(row.show_quick_actions)
|
||||
};
|
||||
}
|
||||
function getAppSettings(db) {
|
||||
@@ -397,6 +409,7 @@ function updateAppSettings(db, patch) {
|
||||
vps_tracker_url: patch.vpsTrackerUrl !== void 0 ? patch.vpsTrackerUrl : current.vps_tracker_url,
|
||||
vps_tracker_integration_token: patch.vpsTrackerIntegrationToken !== void 0 && patch.vpsTrackerIntegrationToken.trim() !== "" ? patch.vpsTrackerIntegrationToken : current.vps_tracker_integration_token,
|
||||
vps_tracker_sync_enabled: patch.vpsTrackerSyncEnabled !== void 0 ? patch.vpsTrackerSyncEnabled : current.vps_tracker_sync_enabled,
|
||||
show_quick_actions: patch.showQuickActions !== void 0 ? patch.showQuickActions : current.show_quick_actions,
|
||||
updated_at: (/* @__PURE__ */ new Date()).toISOString()
|
||||
}).where(eq(appSettings.id, SETTINGS_ID)).run();
|
||||
return getAppSettings(db);
|
||||
@@ -492,6 +505,7 @@ __export(repos_exports, {
|
||||
listUngroupedServices: () => listUngroupedServices,
|
||||
markDnsPendingDelete: () => markDnsPendingDelete,
|
||||
mergeHealthAggregates: () => mergeHealthAggregates,
|
||||
pruneStaleIpHealthStatus: () => pruneStaleIpHealthStatus,
|
||||
reorderServices: () => reorderServices,
|
||||
replaceBindingIps: () => replaceBindingIps,
|
||||
replaceBindingIpsWithMeta: () => replaceBindingIpsWithMeta,
|
||||
@@ -1443,6 +1457,32 @@ function deleteIpHealthStatusForIp(db, scope, refId, ip) {
|
||||
)
|
||||
).run();
|
||||
}
|
||||
function pruneStaleIpHealthStatus(db, activeTargets) {
|
||||
const byRef = /* @__PURE__ */ new Map();
|
||||
for (const t of activeTargets) {
|
||||
const key = `${t.scope}:${t.ref_id}`;
|
||||
let ips = byRef.get(key);
|
||||
if (!ips) {
|
||||
ips = /* @__PURE__ */ new Set();
|
||||
byRef.set(key, ips);
|
||||
}
|
||||
ips.add(t.ip);
|
||||
}
|
||||
let deleted = 0;
|
||||
for (const [key, ips] of byRef) {
|
||||
const sep = key.indexOf(":");
|
||||
const scope = key.slice(0, sep);
|
||||
const refId = Number(key.slice(sep + 1));
|
||||
if (!Number.isFinite(refId)) continue;
|
||||
for (const row of listIpHealthStatus(db, scope, refId)) {
|
||||
if (!ips.has(row.ip)) {
|
||||
deleteIpHealthStatusForIp(db, scope, refId, row.ip);
|
||||
deleted += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return deleted;
|
||||
}
|
||||
function listHealthCheckTargets(db) {
|
||||
const fqdnExpr = sql2`CASE WHEN sb.hostname = '@' OR sb.hostname IS NULL THEN d.zone_name ELSE sb.hostname || '.' || d.zone_name END`;
|
||||
const bindingTargets = db.all(sql2`
|
||||
|
||||
@@ -1687,6 +1687,38 @@ export function deleteIpHealthStatusForIp(
|
||||
.run();
|
||||
}
|
||||
|
||||
/** Drop health rows whose IP is no longer a live probe target for that scope/ref. */
|
||||
export function pruneStaleIpHealthStatus(
|
||||
db: Db,
|
||||
activeTargets: Array<{ scope: HealthCheckScope; ref_id: number; ip: string }>,
|
||||
): number {
|
||||
const byRef = new Map<string, Set<string>>();
|
||||
for (const t of activeTargets) {
|
||||
const key = `${t.scope}:${t.ref_id}`;
|
||||
let ips = byRef.get(key);
|
||||
if (!ips) {
|
||||
ips = new Set();
|
||||
byRef.set(key, ips);
|
||||
}
|
||||
ips.add(t.ip);
|
||||
}
|
||||
|
||||
let deleted = 0;
|
||||
for (const [key, ips] of byRef) {
|
||||
const sep = key.indexOf(":");
|
||||
const scope = key.slice(0, sep) as HealthCheckScope;
|
||||
const refId = Number(key.slice(sep + 1));
|
||||
if (!Number.isFinite(refId)) continue;
|
||||
for (const row of listIpHealthStatus(db, scope, refId)) {
|
||||
if (!ips.has(row.ip)) {
|
||||
deleteIpHealthStatusForIp(db, scope, refId, row.ip);
|
||||
deleted += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return deleted;
|
||||
}
|
||||
|
||||
// --- Health Check Targets ---
|
||||
|
||||
export function listHealthCheckTargets(db: Db): HealthCheckTarget[] {
|
||||
|
||||
Reference in New Issue
Block a user