back_fill_dummy_doc_meta.js 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. const { promisify } = require('util')
  2. const { ObjectId, ReadPreference } = require('mongodb')
  3. const { db, waitForDb } = require('../app/src/infrastructure/mongodb')
  4. const sleep = promisify(setTimeout)
  5. const NOW_IN_S = Date.now() / 1000
  6. const ONE_WEEK_IN_S = 1000 * 60 * 60 * 24 * 7
  7. const TEN_SECONDS = 10 * 1000
  8. const DRY_RUN = process.env.DRY_RUN === 'true'
  9. if (!process.env.FIRST_PROJECT_ID) {
  10. console.error('Set FIRST_PROJECT_ID and re-run.')
  11. process.exit(1)
  12. }
  13. const FIRST_PROJECT_ID = ObjectId(process.env.FIRST_PROJECT_ID)
  14. const INCREMENT_BY_S = parseInt(process.env.INCREMENT_BY_S, 10) || ONE_WEEK_IN_S
  15. const STOP_AT_S = parseInt(process.env.STOP_AT_S, 10) || NOW_IN_S
  16. const LET_USER_DOUBLE_CHECK_INPUTS_FOR =
  17. parseInt(process.env.LET_USER_DOUBLE_CHECK_INPUTS_FOR, 10) || TEN_SECONDS
  18. const DUMMY_NAME = 'unknown.tex'
  19. const DUMMY_TIME = new Date('2021-04-12T00:00:00.000Z')
  20. function getSecondsFromObjectId(id) {
  21. return id.getTimestamp().getTime() / 1000
  22. }
  23. async function main() {
  24. await letUserDoubleCheckInputs()
  25. await waitForDb()
  26. let start = getSecondsFromObjectId(FIRST_PROJECT_ID)
  27. // include the FIRST_PROJECT_ID in the first batch
  28. start -= 1
  29. let nProcessed = 0
  30. while (start < STOP_AT_S) {
  31. const end = start + INCREMENT_BY_S
  32. const startId = ObjectId.createFromTime(start)
  33. const endId = ObjectId.createFromTime(end)
  34. const query = {
  35. project_id: {
  36. // do not include edge
  37. $gt: startId,
  38. // include edge
  39. $lte: endId
  40. },
  41. deleted: true,
  42. name: {
  43. $exists: false
  44. }
  45. }
  46. const docs = await db.docs
  47. .find(query, { readPreference: ReadPreference.SECONDARY })
  48. .project({ _id: 1, project_id: 1 })
  49. .toArray()
  50. if (docs.length) {
  51. const docIds = docs.map(doc => doc._id)
  52. console.log('Back filling dummy meta data for', JSON.stringify(docIds))
  53. await processBatch(docs)
  54. nProcessed += docIds.length
  55. }
  56. console.error('Processed %d until %s', nProcessed, endId)
  57. start = end
  58. }
  59. }
  60. async function processBatch(docs) {
  61. for (const doc of docs) {
  62. const { _id: docId, project_id: projectId } = doc
  63. const deletedProject = await db.deletedProjects.findOne(
  64. { 'deleterData.deletedProjectId': projectId },
  65. {
  66. projection: {
  67. _id: 1,
  68. 'project.deletedDocs': 1
  69. }
  70. }
  71. )
  72. let name = DUMMY_NAME
  73. let deletedAt = DUMMY_TIME
  74. if (deletedProject) {
  75. const project = deletedProject.project
  76. if (project) {
  77. const deletedDoc =
  78. project.deletedDocs &&
  79. project.deletedDocs.find(deletedDoc => docId.equals(deletedDoc._id))
  80. if (deletedDoc) {
  81. console.log('Found deletedDoc for %s', docId)
  82. name = deletedDoc.name
  83. deletedAt = deletedDoc.deletedAt
  84. } else {
  85. console.log('Missing deletedDoc for %s', docId)
  86. }
  87. } else {
  88. console.log('Orphaned deleted doc %s (failed hard deletion)', docId)
  89. }
  90. } else {
  91. console.log('Orphaned deleted doc %s (no deletedProjects entry)', docId)
  92. }
  93. if (DRY_RUN) return
  94. await db.docs.updateOne({ _id: docId }, { $set: { name, deletedAt } })
  95. }
  96. }
  97. async function letUserDoubleCheckInputs() {
  98. console.error(
  99. 'Options:',
  100. JSON.stringify(
  101. {
  102. DRY_RUN,
  103. FIRST_PROJECT_ID,
  104. INCREMENT_BY_S,
  105. STOP_AT_S,
  106. LET_USER_DOUBLE_CHECK_INPUTS_FOR
  107. },
  108. null,
  109. 2
  110. )
  111. )
  112. console.error(
  113. 'Waiting for you to double check inputs for',
  114. LET_USER_DOUBLE_CHECK_INPUTS_FOR,
  115. 'ms'
  116. )
  117. await sleep(LET_USER_DOUBLE_CHECK_INPUTS_FOR)
  118. }
  119. main()
  120. .then(() => {
  121. console.error('Done.')
  122. process.exit(0)
  123. })
  124. .catch(error => {
  125. console.error({ error })
  126. process.exit(1)
  127. })