Files
Checkmate/server/src/db/migration/0007_migrateMaintenanceWindowMonitorIdToArray.ts
T
2026-06-24 10:53:03 -07:00

112 lines
3.1 KiB
TypeScript

import mongoose from "mongoose";
import type { AnyBulkWriteOperation, Document } from "mongodb";
import type { ILogger } from "@/utils/logger.js";
import MaintenanceWindowModel from "../../domain/maintenance-windows/maintenance-window.model.js";
type GroupResult = {
_id: {
teamId: mongoose.Types.ObjectId;
name: string;
start: Date;
end: Date;
repeat: number;
durationUnit: string;
duration: number;
active: boolean;
};
docIds: mongoose.Types.ObjectId[];
monitorIds: mongoose.Types.ObjectId[];
};
export async function migrateMaintenanceWindowMonitorIdToArray(logger: ILogger): Promise<void> {
const SERVICE_NAME = "Migration:MigrateMaintenanceWindowMonitorIdToArray";
try {
logger.info({
service: SERVICE_NAME,
message: "Starting migration of MaintenanceWindow.monitorId to monitorIds array (eager merge)",
});
const db = mongoose.connection.db;
if (!db) {
throw new Error("Database connection is not initialized");
}
// Group old-style docs by their scheduling key.
// Skip rows that already have a monitorIds array — those are either already migrated
// or in a partially-migrated state that needs manual review.
const groups: GroupResult[] = await MaintenanceWindowModel.aggregate<GroupResult>([
{
$match: {
monitorId: { $exists: true, $ne: null },
monitorIds: { $exists: false },
},
},
{
$group: {
_id: {
teamId: "$teamId",
name: "$name",
start: "$start",
end: "$end",
repeat: "$repeat",
durationUnit: "$durationUnit",
duration: "$duration",
active: "$active",
},
docIds: { $push: "$_id" },
monitorIds: { $addToSet: "$monitorId" },
},
},
]);
if (groups.length === 0) {
logger.info({ service: SERVICE_NAME, message: "No MaintenanceWindow documents needed migration" });
return;
}
const bulkOps: AnyBulkWriteOperation<Document>[] = [];
let originalDocCount = 0;
for (const group of groups) {
const { docIds, monitorIds } = group;
originalDocCount += docIds.length;
const [survivorId, ...duplicateIds] = docIds;
bulkOps.push({
updateOne: {
filter: { _id: survivorId },
update: {
$set: { monitorIds },
$unset: { monitorId: "" },
},
},
});
if (duplicateIds.length > 0) {
bulkOps.push({
deleteMany: {
filter: { _id: { $in: duplicateIds } },
},
});
}
}
const result = await MaintenanceWindowModel.collection.bulkWrite(bulkOps, { ordered: true });
const deletedCount = originalDocCount - groups.length;
logger.info({
service: SERVICE_NAME,
message: `Migration complete. Consolidated ${originalDocCount} old document(s) into ${groups.length} group window(s); deleted ${deletedCount} duplicate(s).`,
});
logger.debug({
service: SERVICE_NAME,
message: `bulkWrite result: modified=${result.modifiedCount}, deleted=${result.deletedCount}`,
});
} catch (error) {
const errorMessage = error instanceof Error ? error.message : String(error);
logger.error({ service: SERVICE_NAME, message: `Error during MaintenanceWindow migration: ${errorMessage}` });
throw error;
}
}