back_fill_dummy_doc_meta.js 4.0 KB

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