TpdsProjectFlusher.js 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. const { callbackify } = require('util')
  2. const logger = require('@overleaf/logger')
  3. const DocumentUpdaterHandler = require('../DocumentUpdater/DocumentUpdaterHandler')
  4. const ProjectGetter = require('../Project/ProjectGetter')
  5. const ProjectEntityHandler = require('../Project/ProjectEntityHandler')
  6. const { Project } = require('../../models/Project')
  7. const TpdsUpdateSender = require('./TpdsUpdateSender')
  8. module.exports = {
  9. flushProjectToTpds: callbackify(flushProjectToTpds),
  10. deferProjectFlushToTpds: callbackify(deferProjectFlushToTpds),
  11. flushProjectToTpdsIfNeeded: callbackify(flushProjectToTpdsIfNeeded),
  12. promises: {
  13. flushProjectToTpds,
  14. deferProjectFlushToTpds,
  15. flushProjectToTpdsIfNeeded,
  16. },
  17. }
  18. /**
  19. * Flush a complete project to the TPDS.
  20. */
  21. async function flushProjectToTpds(projectId) {
  22. const project = await ProjectGetter.promises.getProject(projectId, {
  23. name: true,
  24. deferredTpdsFlushCounter: true,
  25. })
  26. await _flushProjectToTpds(project)
  27. }
  28. /**
  29. * Flush a project to TPDS if a flush is pending
  30. */
  31. async function flushProjectToTpdsIfNeeded(projectId) {
  32. const project = await ProjectGetter.promises.getProject(projectId, {
  33. name: true,
  34. deferredTpdsFlushCounter: true,
  35. })
  36. if (project.deferredTpdsFlushCounter > 0) {
  37. await _flushProjectToTpds(project)
  38. }
  39. }
  40. async function _flushProjectToTpds(project) {
  41. logger.debug({ projectId: project._id }, 'flushing project to TPDS')
  42. logger.debug({ projectId: project._id }, 'finished flushing project to TPDS')
  43. await DocumentUpdaterHandler.promises.flushProjectToMongo(project._id)
  44. const [docs, files] = await Promise.all([
  45. ProjectEntityHandler.promises.getAllDocs(project._id),
  46. ProjectEntityHandler.promises.getAllFiles(project._id),
  47. ])
  48. for (const [docPath, doc] of Object.entries(docs)) {
  49. await TpdsUpdateSender.promises.addDoc({
  50. project_id: project._id,
  51. doc_id: doc._id,
  52. path: docPath,
  53. project_name: project.name,
  54. rev: doc.rev || 0,
  55. })
  56. }
  57. for (const [filePath, file] of Object.entries(files)) {
  58. await TpdsUpdateSender.promises.addFile({
  59. project_id: project._id,
  60. file_id: file._id,
  61. path: filePath,
  62. project_name: project.name,
  63. rev: file.rev,
  64. })
  65. }
  66. await _resetDeferredTpdsFlushCounter(project)
  67. }
  68. /**
  69. * Reset the TPDS pending flush counter.
  70. *
  71. * To avoid concurrency problems, the flush counter is not reset if it has been
  72. * incremented since we fetched it from the database.
  73. */
  74. async function _resetDeferredTpdsFlushCounter(project) {
  75. if (project.deferredTpdsFlushCounter > 0) {
  76. await Project.updateOne(
  77. {
  78. _id: project._id,
  79. deferredTpdsFlushCounter: { $lte: project.deferredTpdsFlushCounter },
  80. },
  81. { $set: { deferredTpdsFlushCounter: 0 } }
  82. ).exec()
  83. }
  84. }
  85. /**
  86. * Mark a project as pending a flush to TPDS.
  87. */
  88. async function deferProjectFlushToTpds(projectId) {
  89. await Project.updateOne(
  90. { _id: projectId },
  91. { $inc: { deferredTpdsFlushCounter: 1 } }
  92. ).exec()
  93. }