refactoring notifications

This commit is contained in:
Alex Holliday committed 2026-01-18 23:38:40 +00:00
1 parent 4e9839e2e5
commit a86588f080
6 files changed
+74 -28

No files matched your search

+1 -2
View File
@@ -5,10 +5,9 @@ import MongoDB from "../db/MongoDB.js";
import NetworkService from "../service/infrastructure/networkService.js";
import EmailService from "../service/infrastructure/emailService.js";
import BufferService from "../service/infrastructure/bufferService.js";
import StatusService from "../service/infrastructure/statusService.js";
import NotificationUtils from "../service/infrastructure/notificationUtils.js";
import NotificationService from "../service/infrastructure/notificationService.js";
import { NotificationsService } from "@/service/index.js";
import { NotificationsService, StatusService } from "@/service/index.js";
import ErrorService from "../service/infrastructure/errorService.js";
import SuperSimpleQueueHelper from "../service/infrastructure/SuperSimpleQueue/SuperSimpleQueueHelper.js";
import SuperSimpleQueue from "../service/infrastructure/SuperSimpleQueue/SuperSimpleQueue.js";
+1
View File
@@ -3,3 +3,4 @@ export * from "@/service/infrastructure/networkService.js";
export * from "@/service/infrastructure/notificationProviders/webhook.js";
export * from "@/service/infrastructure/notificationProviders/INotificationProvider.js";
export * from "@/service/infrastructure/notificationsService.js";
export * from "@/service/infrastructure/statusService.js";
@@ -1,18 +1,19 @@
const SERVICE_NAME = "JobQueueHelper";
import type { Monitor } from "@/types/monitor.js";
import { AppError } from "@/utils/AppError.js";
import { INetworkService, INotificationsService } from "@/service/index.js";
import { INetworkService, INotificationsService, IStatusService } from "@/service/index.js";
class SuperSimpleQueueHelper {
static SERVICE_NAME = SERVICE_NAME;
private db: any;
private logger: any;
private networkService: INetworkService;
private statusService: any;
private statusService: IStatusService;
private notificationService: any;
private notificationsService: INotificationsService;
private checkService: any;
private buffer: any;
private incidentService: any;
constructor({
db,
@@ -23,15 +24,17 @@ class SuperSimpleQueueHelper {
notificationsService,
checkService,
buffer,
incidentService,
}: {
db: any;
logger: any;
networkService: INetworkService;
statusService: any;
statusService: IStatusService;
notificationService: any;
notificationsService: INotificationsService;
checkService: any;
buffer: any;
incidentService: any;
}) {
this.db = db;
this.logger = logger;
@@ -41,6 +44,7 @@ class SuperSimpleQueueHelper {
this.checkService = checkService;
this.buffer = buffer;
this.notificationsService = notificationsService;
this.incidentService = incidentService;
}
get serviceName() {
@@ -82,10 +86,9 @@ class SuperSimpleQueueHelper {
// Step 4. Update monitor status
const statusChangeResult = await this.statusService.updateMonitorStatus(status, check);
// Step 5 handle incidents and notifications
if (statusChangeResult.statusChanged === true) {
this.notificationsService.handleNotifications(monitor, status);
}
// Step 5 handle notifications
this.notificationsService.handleNotifications(monitor, status, statusChangeResult.prevStatus, statusChangeResult.statusChanged);
// this.notificationService
// .handleNotifications({
@@ -1,11 +1,49 @@
import type { Monitor, MonitorStatusResponse } from "@/types/index.js";
import type { HardwareStatusPayload, Monitor, MonitorStatusResponse } from "@/types/index.js";
export interface INotificationsService {
handleNotifications: (monitor: Monitor, monitorStatusResponse: MonitorStatusResponse) => Promise<void>;
handleNotifications: (
monitor: Monitor,
monitorStatusResponse: MonitorStatusResponse,
prevStatus: boolean | undefined,
statusChanged: boolean
) => Promise<boolean>;
}
export class NotificationsService implements INotificationsService {
handleNotifications = async (monitor: Monitor, monitorStatusResponse: MonitorStatusResponse) => {
console.log(JSON.stringify(monitor, null, 2));
console.log(JSON.stringify(monitorStatusResponse, null, 2));
handleNotifications = async (
monitor: Monitor,
monitorStatusResponse: MonitorStatusResponse,
prevStatus: boolean | undefined,
statusChanged: boolean
) => {
const { type } = monitor;
const payload = monitorStatusResponse.payload as HardwareStatusPayload;
// If this is a non-hardeware type monitor and status did not change, we're done
if (type !== "hardware" && statusChanged === false) return false;
// if prevStatus is undefined, monitor is resuming, we're done
if (type !== "hardware" && prevStatus === undefined) return false;
// Deal with hardware thresholds
if (type === "hardware") {
const thresholds = monitor.thresholds;
if (thresholds === undefined) return false; // No thresholds set, we're done
const metrics = payload?.data ?? null;
if (metrics === null) return false; // No metrics, we're done
// We shoul dsend a notificaiton
console.log(JSON.stringify(monitor, null, 2));
console.log(JSON.stringify(monitorStatusResponse, null, 2));
// const [alerts, discordContent] = await this.notificationUtils.buildHardwareAlerts(networkResponse);
// if (alerts.length === 0) return false;
// const { subject, html } = await this.notificationUtils.buildHardwareEmail(networkResponse, alerts);
// const content = await this.notificationUtils.buildHardwareNotificationMessage(alerts, monitor);
// const webhookBody = await this.notificationUtils.buildHardwareWebhookBody(alerts, monitor);
// const success = await this.notifyAll({ notificationIDs, subject, html, content, discordContent, webhookBody });
return true;
}
return false;
};
}
@@ -12,7 +12,17 @@ import type {
} from "@/types/index.js";
const SERVICE_NAME = "StatusService";
class StatusService {
export interface IStatusService {
updateRunningStats({ monitor, networkResponse }: { monitor: Monitor; networkResponse: any }): Promise<boolean>;
getStatusString(status: boolean | undefined): string;
handleIncidentForCheck(check: any, monitor: Monitor, action: any, errorContext?: string): Promise<void>;
updateMonitorStatus(
statusResponse: MonitorStatusResponse<PageSpeedStatusPayload | HardwareStatusPayload | undefined>,
check: Check
): Promise<StatusChangeResult>;
}
export class StatusService implements IStatusService {
static SERVICE_NAME = SERVICE_NAME;
private db: any;
private logger: any;
@@ -108,11 +118,10 @@ class StatusService {
return "unknown";
};
handleIncidentForCheck = async (check: any, monitor: Monitor, action: any, errorContext = "incident handling") => {
handleIncidentForCheck = async (check: Check, monitor: Monitor, action: any, errorContext = "incident handling") => {
try {
let savedCheck = check;
if (!check._id) {
let savedCheck;
if (!check.id) {
try {
const checkModel = new CheckModel(check);
savedCheck = await checkModel.save();
@@ -130,7 +139,7 @@ class StatusService {
}
}
if (savedCheck && savedCheck._id) {
if (savedCheck && savedCheck.id) {
try {
this.buffer.addIncidentToBuffer({ monitor, check: savedCheck, action });
} catch (incidentError: any) {
@@ -167,13 +176,10 @@ class StatusService {
this.updateRunningStats({ monitor, networkResponse: statusResponse });
// If the status window size has changed, empty
while (monitor.statusWindow.length > monitor.statusWindowSize) {
monitor.statusWindow.shift();
}
// Update status sliding window
monitor.statusWindow = monitor.statusWindow || [];
monitor.statusWindow.push(status);
if (monitor.statusWindow.length > monitor.statusWindowSize) {
while (monitor.statusWindow.length > monitor.statusWindowSize) {
monitor.statusWindow.shift();
}
@@ -181,9 +187,9 @@ class StatusService {
monitor.status = status;
}
const prevStatus = monitor.status;
let newStatus = monitor.status;
let statusChanged = false;
const prevStatus = monitor.status;
// Return early if not enough data points
if (monitor.statusWindow.length < monitor.statusWindowSize) {
@@ -316,4 +322,3 @@ class StatusService {
}
};
}
export default StatusService;
+1 -1
View File
@@ -13,7 +13,7 @@ import type {
MonitorType,
} from "@/types/index.js";
export interface MonitorStatusResponse<T = unknown> {
export interface MonitorStatusResponse<T = any> {
monitorId: string;
teamId: string;
type: MonitorType;