|
@@ -0,0 +1,88 @@
|
|
|
|
|
+// @ts-check
|
|
|
|
|
+import { db } from '../app/src/infrastructure/mongodb.js'
|
|
|
|
|
+import { batchedUpdate } from '@overleaf/mongo-utils/batchedUpdate.js'
|
|
|
|
|
+import { scriptRunner } from './lib/ScriptRunner.mjs'
|
|
|
|
|
+import CollaboratorsHandler from '../app/src/Features/Collaborators/CollaboratorsHandler.js'
|
|
|
|
|
+
|
|
|
|
|
+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<void>} trackProgress
|
|
|
|
|
+ * @returns {Promise<void>}
|
|
|
|
|
+ * @async
|
|
|
|
|
+ */
|
|
|
|
|
+async function main(trackProgress) {
|
|
|
|
|
+ let projectsProcessed = 0
|
|
|
|
|
+ await batchedUpdate(
|
|
|
|
|
+ db.projects,
|
|
|
|
|
+ {},
|
|
|
|
|
+ /**
|
|
|
|
|
+ * @param {Array<Project>} projects
|
|
|
|
|
+ * @return {Promise<void>}
|
|
|
|
|
+ */
|
|
|
|
|
+ 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)
|
|
|
|
|
+}
|