diff --git a/client/src/pages/incidents/IncidentTable.tsx b/client/src/pages/incidents/IncidentTable.tsx index d1cee514d..b00a8c68c 100644 --- a/client/src/pages/incidents/IncidentTable.tsx +++ b/client/src/pages/incidents/IncidentTable.tsx @@ -37,7 +37,7 @@ export const IncidentTable = ({ id: "name", content: t("incidentsTableMonitorName"), render: (row) => { - return row.monitorId.name || "N/A"; + return row.monitorId?.name || "N/A"; }, }, { @@ -70,7 +70,7 @@ export const IncidentTable = ({ render: (row) => { return ( - {row.monitorId.status} + {row.monitorId?.status} ); }, diff --git a/server/src/db/models/monitors/Monitor.ts b/server/src/db/models/monitors/Monitor.ts index b190647dd..050185adb 100644 --- a/server/src/db/models/monitors/Monitor.ts +++ b/server/src/db/models/monitors/Monitor.ts @@ -1,5 +1,5 @@ import mongoose, { Schema, Document, Types } from "mongoose"; -import { Check, MonitorStats } from "@/db/models/index.js"; +import { Check, Incident, MonitorStats } from "@/db/models/index.js"; export const MonitorTypes = [ "http", @@ -99,6 +99,7 @@ MonitorSchema.pre( const monitorId = this._id; await Check.deleteMany({ "metadata.monitorId": monitorId }); await MonitorStats.deleteMany({ monitorId }); + await Incident.deleteMany({ monitorId }); next(); } catch (error: any) { next(error); @@ -117,6 +118,7 @@ MonitorSchema.pre( if (monitorIds.length > 0) { await Check.deleteMany({ "metadata.monitorId": { $in: monitorIds } }); await MonitorStats.deleteMany({ monitorId: { $in: monitorIds } }); + await Incident.deleteMany({ monitorId: { $in: monitorIds } }); } next(); } catch (error: any) { diff --git a/server/src/services/business/IncidentService.ts b/server/src/services/business/IncidentService.ts index 5ad6653a9..6fcd11930 100644 --- a/server/src/services/business/IncidentService.ts +++ b/server/src/services/business/IncidentService.ts @@ -1,4 +1,10 @@ -import { IIncident, Incident, IMonitor, ICheck } from "@/db/models/index.js"; +import { + IIncident, + Incident, + IMonitor, + Monitor, + ICheck, +} from "@/db/models/index.js"; import type { ResolutionType } from "@/db/models/index.js"; import mongoose from "mongoose"; import { getChildLogger } from "@/logger/Logger.js"; @@ -39,10 +45,11 @@ export interface IIncidentService { teamId: mongoose.Types.ObjectId, incidentId: mongoose.Types.ObjectId ) => Promise; + cleanupOrphanedIncidents: () => Promise; } const SERVICE_NAME = "IncidentService"; - +const logger = getChildLogger(SERVICE_NAME); class IncidentService implements IIncidentService { public SERVICE_NAME: string; constructor() { @@ -199,6 +206,20 @@ class IncidentService implements IIncidentService { }); return result.deletedCount === 1; }; + + async cleanupOrphanedIncidents() { + try { + const monitorIds = await Monitor.find().distinct("_id"); + const result = await Incident.deleteMany({ + monitorId: { $nin: monitorIds }, + }); + logger.info(`Deleted ${result.deletedCount} orphaned Incidents.`); + return true; + } catch (error) { + logger.error("Error cleaning up orphaned Incidents:", error); + return false; + } + } } export default IncidentService; diff --git a/server/src/services/infrastructure/JobGenerator.ts b/server/src/services/infrastructure/JobGenerator.ts index 6324046a6..971d939c7 100644 --- a/server/src/services/infrastructure/JobGenerator.ts +++ b/server/src/services/infrastructure/JobGenerator.ts @@ -98,6 +98,7 @@ class JobGenerator implements IJobGenerator { try { await this.checkService.cleanupOrphanedChecks(); await this.monitorStatsService.cleanupOrphanedMonitorStats(); + await this.incidentService.cleanupOrphanedIncidents(); } catch (error) { throw error; }