back_fill_deleted_files.js 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. const WRITE_CONCURRENCY = parseInt(process.env.WRITE_CONCURRENCY, 10) || 10
  2. const { batchedUpdate } = require('./helpers/batchedUpdate')
  3. const { promiseMapWithLimit, promisify } = require('../app/src/util/promises')
  4. const { db } = require('../app/src/infrastructure/mongodb')
  5. const sleep = promisify(setTimeout)
  6. const PERFORM_CLEANUP = process.argv.pop() === '--perform-cleanup'
  7. const LET_USER_DOUBLE_CHECK_INPUTS_FOR = parseInt(
  8. process.env.LET_USER_DOUBLE_CHECK_INPUTS_FOR || 10 * 1000,
  9. 10
  10. )
  11. async function main() {
  12. await letUserDoubleCheckInputs()
  13. await batchedUpdate(
  14. 'projects',
  15. // array is not empty ~ array has one item
  16. { 'deletedFiles.0': { $exists: true } },
  17. processBatch,
  18. { _id: 1, deletedFiles: 1 }
  19. )
  20. }
  21. main()
  22. .then(() => {
  23. process.exit(0)
  24. })
  25. .catch(error => {
  26. console.error({ error })
  27. process.exit(1)
  28. })
  29. async function processBatch(_, projects) {
  30. await promiseMapWithLimit(WRITE_CONCURRENCY, projects, processProject)
  31. }
  32. async function processProject(project) {
  33. await backFillFiles(project)
  34. if (PERFORM_CLEANUP) {
  35. await cleanupProject(project)
  36. }
  37. }
  38. async function backFillFiles(project) {
  39. const projectId = project._id
  40. filterDuplicatesInPlace(project)
  41. project.deletedFiles.forEach(file => {
  42. file.projectId = projectId
  43. })
  44. await db.deletedFiles.insertMany(project.deletedFiles)
  45. }
  46. function filterDuplicatesInPlace(project) {
  47. const fileIds = new Set()
  48. project.deletedFiles = project.deletedFiles.filter(file => {
  49. const id = file._id.toString()
  50. if (fileIds.has(id)) return false
  51. fileIds.add(id)
  52. return true
  53. })
  54. }
  55. async function cleanupProject(project) {
  56. await db.projects.updateOne(
  57. { _id: project._id },
  58. { $set: { deletedFiles: [] } }
  59. )
  60. }
  61. async function letUserDoubleCheckInputs() {
  62. if (PERFORM_CLEANUP) {
  63. console.error('BACK FILLING AND PERFORMING CLEANUP')
  64. } else {
  65. console.error(
  66. 'BACK FILLING ONLY - You will need to rerun with --perform-cleanup'
  67. )
  68. }
  69. console.error(
  70. 'Waiting for you to double check inputs for',
  71. LET_USER_DOUBLE_CHECK_INPUTS_FOR,
  72. 'ms'
  73. )
  74. await sleep(LET_USER_DOUBLE_CHECK_INPUTS_FOR)
  75. }