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 { 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([ { $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[] = []; 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; } }