/** * Rollback script for LNM-21-102-DEV legacy advisory backfill migration. * Removes backfilled observations and linksets by querying the backfill_marker field, * then clears the tombstone markers from advisory_raw. * * Usage: * mongo concelier ops/devops/scripts/rollback-lnm-backfill.js * * Environment variables: * DRY_RUN - if set to "1", only reports what would be deleted without making changes. * BATCH_SIZE - optional batch size for deletions (default 500). * * After running this script, delete the migration record: * db.schema_migrations.deleteOne({ _id: "20251127_lnm_legacy_backfill" }) * * Then restart the Concelier service. */ (function () { var BACKFILL_MARKER = "lnm_21_102_dev"; function toInt(value, fallback) { var parsed = parseInt(value, 10); return Number.isFinite(parsed) && parsed > 0 ? parsed : fallback; } function toBool(value) { return value === "1" || value === "true" || value === true; } var dryRun = typeof DRY_RUN !== "undefined" ? toBool(DRY_RUN) : false; var batchSize = typeof BATCH_SIZE !== "undefined" ? toInt(BATCH_SIZE, 500) : 500; var database = db.getName ? db.getSiblingDB(db.getName()) : db; if (!database) { throw new Error("Unable to resolve database handle"); } print(""); print("== LNM-21-102-DEV Backfill Rollback =="); print("Database : " + database.getName()); print("Dry Run : " + dryRun); print("Batch Size: " + batchSize); print(""); // Step 1: Count and delete backfilled observations var observationsCollection = database.getCollection("advisory_observations"); var observationsFilter = { backfill_marker: BACKFILL_MARKER }; var observationsCount = observationsCollection.countDocuments(observationsFilter); print("Found " + observationsCount + " backfilled observations to remove."); if (!dryRun && observationsCount > 0) { var obsResult = observationsCollection.deleteMany(observationsFilter); print("Deleted " + obsResult.deletedCount + " observations."); } // Step 2: Count and delete backfilled linksets var linksetsCollection = database.getCollection("advisory_linksets"); var linksetsFilter = { backfill_marker: BACKFILL_MARKER }; var linksetsCount = linksetsCollection.countDocuments(linksetsFilter); print("Found " + linksetsCount + " backfilled linksets to remove."); if (!dryRun && linksetsCount > 0) { var linkResult = linksetsCollection.deleteMany(linksetsFilter); print("Deleted " + linkResult.deletedCount + " linksets."); } // Step 3: Clear tombstone markers from advisory_raw var rawCollection = database.getCollection("advisory_raw"); var rawFilter = { backfill_marker: BACKFILL_MARKER }; var rawCount = rawCollection.countDocuments(rawFilter); print("Found " + rawCount + " advisory_raw documents with tombstone markers to clear."); if (!dryRun && rawCount > 0) { var rawResult = rawCollection.updateMany(rawFilter, { $unset: { backfill_marker: "" } }); print("Cleared tombstone markers from " + rawResult.modifiedCount + " advisory_raw documents."); } // Step 4: Summary print(""); print("== Rollback Summary =="); if (dryRun) { print("DRY RUN - No changes were made."); print("Would delete " + observationsCount + " observations."); print("Would delete " + linksetsCount + " linksets."); print("Would clear " + rawCount + " tombstone markers."); } else { print("Observations deleted: " + observationsCount); print("Linksets deleted : " + linksetsCount); print("Tombstones cleared : " + rawCount); } print(""); print("Next steps:"); print("1. Delete the migration record:"); print(' db.schema_migrations.deleteOne({ _id: "20251127_lnm_legacy_backfill" })'); print("2. Restart the Concelier service."); print(""); })();