| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129 |
- const { promisify } = require('util')
- const { ObjectId, ReadPreference } = require('mongodb')
- const { db, waitForDb } = require('../../app/src/infrastructure/mongodb')
- const sleep = promisify(setTimeout)
- const _ = require('lodash')
- const NOW_IN_S = Date.now() / 1000
- const ONE_WEEK_IN_S = 60 * 60 * 24 * 7
- const TEN_SECONDS = 10 * 1000
- function getSecondsFromObjectId(id) {
- return id.getTimestamp().getTime() / 1000
- }
- async function main(options) {
- if (!options) {
- options = {}
- }
- _.defaults(options, {
- projectId: process.env.PROJECT_ID,
- dryRun: process.env.DRY_RUN !== 'false',
- verboseLogging: process.env.VERBOSE_LOGGING === 'true',
- firstProjectId: process.env.FIRST_PROJECT_ID
- ? ObjectId(process.env.FIRST_PROJECT_ID)
- : ObjectId('4b3d3b3d0000000000000000'), // timestamped to 2010-01-01T00:01:01.000Z
- incrementByS: parseInt(process.env.INCREMENT_BY_S, 10) || ONE_WEEK_IN_S,
- batchSize: parseInt(process.env.BATCH_SIZE, 10) || 1000,
- stopAtS: parseInt(process.env.STOP_AT_S, 10) || NOW_IN_S,
- letUserDoubleCheckInputsFor:
- parseInt(process.env.LET_USER_DOUBLE_CHECK_INPUTS_FOR, 10) || TEN_SECONDS,
- })
- if (options.projectId) {
- await waitForDb()
- const { modifiedCount } = await db.projects.updateOne(
- {
- _id: ObjectId(options.projectId),
- 'overleaf.history.allowDowngrade': true,
- },
- { $unset: { 'overleaf.history.allowDowngrade': 1 } }
- )
- console.log(`modifiedCount: ${modifiedCount}`)
- process.exit(0)
- }
- await letUserDoubleCheckInputs(options)
- await waitForDb()
- let startId = options.firstProjectId
- let totalProcessed = 0
- while (getSecondsFromObjectId(startId) <= options.stopAtS) {
- let batchProcessed = 0
- const end = getSecondsFromObjectId(startId) + options.incrementByS
- let endId = ObjectId.createFromTime(end)
- const query = {
- _id: {
- // include edge
- $gte: startId,
- // exclude edge
- $lt: endId,
- },
- 'overleaf.history.allowDowngrade': true,
- }
- const projects = await db.projects
- .find(query, { readPreference: ReadPreference.SECONDARY })
- .project({ _id: 1 })
- .limit(options.batchSize)
- .toArray()
- if (projects.length) {
- const projectIds = projects.map(project => project._id)
- if (options.verboseLogging) {
- console.log(
- `Processing projects with ids: ${JSON.stringify(projectIds)}`
- )
- } else {
- console.log(`Processing ${projects.length} projects`)
- }
- if (!options.dryRun) {
- await db.projects.updateMany(
- { _id: { $in: projectIds } },
- { $unset: { 'overleaf.history.allowDowngrade': 1 } }
- )
- } else {
- console.log(
- `skipping update of ${projectIds.length} projects in dry-run mode`
- )
- }
- totalProcessed += projectIds.length
- batchProcessed += projectIds.length
- if (projects.length === options.batchSize) {
- endId = projects[projects.length - 1]._id
- }
- }
- console.error(
- `Processed ${batchProcessed} from ${startId} until ${endId} (${totalProcessed} processed in total)`
- )
- startId = endId
- }
- }
- async function letUserDoubleCheckInputs(options) {
- console.error('Options:', JSON.stringify(options, null, 2))
- console.error(
- 'Waiting for you to double check inputs for',
- options.letUserDoubleCheckInputsFor,
- 'ms'
- )
- await sleep(options.letUserDoubleCheckInputsFor)
- }
- module.exports = main
- if (require.main === module) {
- main()
- .then(() => {
- console.error('Done.')
- process.exit(0)
- })
- .catch(error => {
- console.error({ error })
- process.exit(1)
- })
- }
|