// @ts-check import { db } from '../app/src/infrastructure/mongodb.mjs' import { batchedUpdate } from '@overleaf/mongo-utils/batchedUpdate.js' import { scriptRunner } from './lib/ScriptRunner.mjs' import CollaboratorsHandler from '../app/src/Features/Collaborators/CollaboratorsHandler.mjs' const DRY_RUN = !process.argv.includes('--dry-run=false') const DEBUG = process.argv.includes('--debug=true') // Deployment procedure: // Run it locally (not dry run) // Run it on staging (dry run then real and then real). Maybe leave it a few days but might not get good feedback // Run on prod on a small number of projects to start with, then on all projects (using BATCH_RANGE_START and BATCH_RANGE_END env vars) // Are there race conditions here? If someone is editing in parallel. Is it worth doing atomic queries? /** * @typedef {Object} Project * @property {any} _id * @property {Object} track_changes */ /** * @param {(progress: string) => Promise} trackProgress * @returns {Promise} * @async */ async function main(trackProgress) { let projectsProcessed = 0 await batchedUpdate( db.projects, {}, /** * @param {Array} projects * @return {Promise} */ async function projects(projects) { for (const project of projects) { projectsProcessed += 1 if (projectsProcessed % 100000 === 0) { console.log(projectsProcessed, 'projects processed') } await processProject(project) } }, { _id: 1, track_changes: 1 }, undefined, { trackProgress } ) } async function processProject(project) { if (DEBUG) { console.log( `Processing project ${project._id} with track_changes: ${JSON.stringify( project.track_changes )}` ) } const newTrackChangesState = await CollaboratorsHandler.promises.convertTrackChangesToExplicitFormat( project._id, project.track_changes ) if (DEBUG) { console.log( `Processed project ${project._id} to have new track_changes: ${JSON.stringify( newTrackChangesState )}` ) } if (!DRY_RUN) { await db.projects.updateOne( { _id: project._id }, { $set: { track_changes: newTrackChangesState } } ) } } try { await scriptRunner(main) process.exit(0) } catch (error) { console.error(error) process.exit(1) }