Merge pull request #29487 from overleaf/ii-subscpriptions-v1-id-index

[web] Update v1_id index to be unique

GitOrigin-RevId: 99ba8f10a1b34f7717f57cd5495d4159019343d1
This commit is contained in:
ilkin-overleaf
2025-11-17 16:46:33 +02:00
committed by Copybot
parent 9ea8031055
commit 341b9b9e0b

View File

@@ -0,0 +1,90 @@
import Helpers from './lib/helpers.mjs'
const tags = ['saas']
const originalIndexes = [
{
key: { v1_id: 1 },
name: 'v1_id_1',
sparse: true,
},
]
const newIndexes = [
{
key: { v1_id: 1 },
name: 'v1_id_3',
unique: true,
sparse: true,
},
]
async function removeNullV1Ids(collection) {
// Remove the v1_id field from documents where it's null
const result = await collection.updateMany(
{ v1_id: { $type: 'null' } },
{ $unset: { v1_id: 1 } }
)
console.log(
`Removed \`{ v1_id: null }\` field from ${result.modifiedCount} documents`
)
}
async function assertNoDuplicateV1Ids(collection) {
const duplicates = await collection
.aggregate([
{ $match: { v1_id: { $exists: true, $ne: null } } },
{
$group: {
_id: '$v1_id',
count: { $sum: 1 },
docs: { $push: '$_id' },
},
},
{ $match: { count: { $gt: 1 } } },
])
.toArray()
if (duplicates.length > 0) {
const duplicateDetails = duplicates.map(dup => ({
v1_id: dup._id,
count: dup.count,
docs: dup.docs,
}))
throw new Error(
`Duplicate v1_id values found. Migration aborted to prevent data loss. Details: ${JSON.stringify(
duplicateDetails,
null,
2
)}`
)
}
}
const migrate = async client => {
const { db } = client
// precheck (keep old index intact if failing)
await assertNoDuplicateV1Ids(db.subscriptions)
await removeNullV1Ids(db.subscriptions)
await Helpers.addIndexesToCollection(db.subscriptions, newIndexes)
await Helpers.dropIndexesFromCollection(
db.subscriptions,
// drop the 20251010082205 index too which wasn't working properly
originalIndexes.concat({ name: 'v1_id_2' })
)
}
const rollback = async client => {
const { db } = client
// recreate the original non-unique sparse index
await Helpers.addIndexesToCollection(db.subscriptions, originalIndexes)
await Helpers.dropIndexesFromCollection(db.subscriptions, newIndexes)
}
export default {
tags,
migrate,
rollback,
}