Merge pull request #9030 from overleaf/msm-update-allowdowngrade-script

[scripts] Change batching in `unset_allow_downgrade.js`

GitOrigin-RevId: 42542f1b2ca75d184cf2d812f3ebaf291a5992b6
This commit is contained in:
Jakob Ackermann 2022-07-28 15:37:45 +01:00 committed by Copybot
parent 79cdf5e65e
commit a31f30ed44

View file

@ -1,46 +1,129 @@
const BATCH_SIZE = parseInt(process.env.BATCH_SIZE, 10) || 100
// persist fallback in order to keep batchedUpdate in-sync
process.env.BATCH_SIZE = BATCH_SIZE
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 PROJECT_ID = process.env.PROJECT_ID
const NOW_IN_S = Date.now() / 1000
const ONE_WEEK_IN_S = 60 * 60 * 24 * 7
const TEN_SECONDS = 10 * 1000
const {
db,
waitForDb,
ObjectId,
} = require('../../app/src/infrastructure/mongodb')
const { batchedUpdate } = require('../helpers/batchedUpdate')
function getSecondsFromObjectId(id) {
return id.getTimestamp().getTime() / 1000
}
console.log({
PROJECT_ID,
BATCH_SIZE,
VERBOSE_LOGGING: process.env.VERBOSE_LOGGING, // for batchedUpdate() logging
})
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,
})
async function main() {
if (PROJECT_ID) {
if (options.projectId) {
await waitForDb()
const { modifiedCount } = await db.projects.updateOne(
{ _id: ObjectId(PROJECT_ID), 'overleaf.history.allowDowngrade': true },
{
_id: ObjectId(options.projectId),
'overleaf.history.allowDowngrade': true,
},
{ $unset: { 'overleaf.history.allowDowngrade': 1 } }
)
console.log(`modifiedCount: ${modifiedCount}`)
} else {
await batchedUpdate(
'projects',
{ 'overleaf.history.allowDowngrade': true },
{ $unset: { 'overleaf.history.allowDowngrade': 1 } }
)
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
}
console.log('Final')
}
main()
.then(() => {
console.error('Done.')
process.exit(0)
})
.catch(error => {
console.error({ error })
process.exit(1)
})
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)
})
}