type only imports, add empty guard for threshold breaches do Docker monitors don't get this

This commit is contained in:
Alex Holliday committed 2026-09-24 13:20:03 -07:00
1 parent 11c89d150a
commit f2c23636fe
4 files changed
+11 -4

No files matched your search

@@ -1,4 +1,4 @@
import { HardwareMetricKey } from "@/domain/monitors/monitor.type.js";
import type { HardwareMetricKey } from "@/domain/monitors/monitor.type.js";
export const NotificationChannels = [
"email",
+2 -2
View File
@@ -2,10 +2,10 @@ import { IMonitorStatsRepository } from "@/domain/monitor-stats/monitor-stats.re
import { IMonitorsRepository } from "@/domain/monitors/monitor.repository.interface.js";
import type { Check, CheckDiskInfo } from "@/domain/checks/check.type.js";
import {
HardwareBreaches,
HardwareCounters,
HardwareMetricKeys,
MonitorStatuses,
type HardwareBreaches,
type HardwareCounters,
type Monitor,
type MonitorStatus,
} from "@/domain/monitors/monitor.type.js";
+1 -1
View File
@@ -298,7 +298,7 @@ export class WorkerPipeline implements IWorkerPipeline {
decision.incidentReason = "status_down";
decision.notificationReason = "status_change";
} else if (monitor.status === "breached") {
decision.thresholdBreaches = statusChange.thresholdBreaches;
if (statusChange.thresholdBreaches) decision.thresholdBreaches = statusChange.thresholdBreaches;
decision.shouldCreateIncident = true;
decision.shouldSendNotification = true;
decision.incidentReason = "threshold_breach";
@@ -864,6 +864,13 @@ describe("WorkerPipeline", () => {
expect(decision).not.toHaveProperty("thresholdBreaches");
});
// StatusService only sets thresholdBreaches for hardware monitors; a docker breach must not leave the key behind holding undefined.
it("leaves threshold breaches off a breached decision when the status change carries none", async () => {
const decision = await decide(makeStatusChange({ status: "breached", statusChanged: true, prevStatus: "up" }));
expect(decision).toMatchObject({ shouldCreateIncident: true, incidentReason: "threshold_breach" });
expect(decision).not.toHaveProperty("thresholdBreaches");
});
// Each decision starts from a shared template. A transition must not leak its flags into the next decision
// the same pipeline makes, whether that is a no-op evaluation or a degraded-egress short-circuit.
it("starts every decision clean after a transition on the same pipeline", async () => {