MongoManager.js 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. /* eslint-disable
  2. camelcase,
  3. handle-callback-err,
  4. no-unused-vars,
  5. */
  6. // TODO: This file was created by bulk-decaffeinate.
  7. // Fix any style issues and re-enable lint.
  8. /*
  9. * decaffeinate suggestions:
  10. * DS102: Remove unnecessary code created because of implicit returns
  11. * DS207: Consider shorter variations of null checks
  12. * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
  13. */
  14. let MongoManager
  15. const { db, ObjectId } = require('./mongodb')
  16. const PackManager = require('./PackManager')
  17. const async = require('async')
  18. const _ = require('underscore')
  19. const metrics = require('@overleaf/metrics')
  20. const logger = require('logger-sharelatex')
  21. module.exports = MongoManager = {
  22. getLastCompressedUpdate(doc_id, callback) {
  23. if (callback == null) {
  24. callback = function (error, update) {}
  25. }
  26. return db.docHistory
  27. .find(
  28. { doc_id: ObjectId(doc_id.toString()) },
  29. // only return the last entry in a pack
  30. { projection: { pack: { $slice: -1 } } }
  31. )
  32. .sort({ v: -1 })
  33. .limit(1)
  34. .toArray(function (error, compressedUpdates) {
  35. if (error != null) {
  36. return callback(error)
  37. }
  38. return callback(null, compressedUpdates[0] || null)
  39. })
  40. },
  41. peekLastCompressedUpdate(doc_id, callback) {
  42. // under normal use we pass back the last update as
  43. // callback(null,update,version).
  44. //
  45. // when we have an existing last update but want to force a new one
  46. // to start, we pass it back as callback(null,null,version), just
  47. // giving the version so we can check consistency.
  48. if (callback == null) {
  49. callback = function (error, update, version) {}
  50. }
  51. return MongoManager.getLastCompressedUpdate(
  52. doc_id,
  53. function (error, update) {
  54. if (error != null) {
  55. return callback(error)
  56. }
  57. if (update != null) {
  58. if (update.broken) {
  59. // marked as broken so we will force a new op
  60. return callback(null, null)
  61. } else if (update.pack != null) {
  62. if (update.finalised) {
  63. // no more ops can be appended
  64. return callback(
  65. null,
  66. null,
  67. update.pack[0] != null ? update.pack[0].v : undefined
  68. )
  69. } else {
  70. return callback(
  71. null,
  72. update,
  73. update.pack[0] != null ? update.pack[0].v : undefined
  74. )
  75. }
  76. } else {
  77. return callback(null, update, update.v)
  78. }
  79. } else {
  80. return PackManager.getLastPackFromIndex(
  81. doc_id,
  82. function (error, pack) {
  83. if (error != null) {
  84. return callback(error)
  85. }
  86. if (
  87. (pack != null ? pack.inS3 : undefined) != null &&
  88. (pack != null ? pack.v_end : undefined) != null
  89. ) {
  90. return callback(null, null, pack.v_end)
  91. }
  92. return callback(null, null)
  93. }
  94. )
  95. }
  96. }
  97. )
  98. },
  99. backportProjectId(project_id, doc_id, callback) {
  100. if (callback == null) {
  101. callback = function (error) {}
  102. }
  103. return db.docHistory.updateMany(
  104. {
  105. doc_id: ObjectId(doc_id.toString()),
  106. project_id: { $exists: false },
  107. },
  108. {
  109. $set: { project_id: ObjectId(project_id.toString()) },
  110. },
  111. callback
  112. )
  113. },
  114. getProjectMetaData(project_id, callback) {
  115. if (callback == null) {
  116. callback = function (error, metadata) {}
  117. }
  118. return db.projectHistoryMetaData.findOne(
  119. {
  120. project_id: ObjectId(project_id.toString()),
  121. },
  122. callback
  123. )
  124. },
  125. setProjectMetaData(project_id, metadata, callback) {
  126. if (callback == null) {
  127. callback = function (error) {}
  128. }
  129. return db.projectHistoryMetaData.updateOne(
  130. {
  131. project_id: ObjectId(project_id),
  132. },
  133. {
  134. $set: metadata,
  135. },
  136. {
  137. upsert: true,
  138. },
  139. callback
  140. )
  141. },
  142. upgradeHistory(project_id, callback) {
  143. // preserve the project's existing history
  144. if (callback == null) {
  145. callback = function (error) {}
  146. }
  147. return db.docHistory.updateMany(
  148. {
  149. project_id: ObjectId(project_id),
  150. temporary: true,
  151. expiresAt: { $exists: true },
  152. },
  153. {
  154. $set: { temporary: false },
  155. $unset: { expiresAt: '' },
  156. },
  157. callback
  158. )
  159. },
  160. ensureIndices() {
  161. // For finding all updates that go into a diff for a doc
  162. db.docHistory.ensureIndex({ doc_id: 1, v: 1 }, { background: true })
  163. // For finding all updates that affect a project
  164. db.docHistory.ensureIndex(
  165. { project_id: 1, 'meta.end_ts': 1 },
  166. { background: true }
  167. )
  168. // For finding updates that don't yet have a project_id and need it inserting
  169. db.docHistory.ensureIndex(
  170. { doc_id: 1, project_id: 1 },
  171. { background: true }
  172. )
  173. // For finding project meta-data
  174. db.projectHistoryMetaData.ensureIndex(
  175. { project_id: 1 },
  176. { background: true }
  177. )
  178. // TTL index for auto deleting week old temporary ops
  179. db.docHistory.ensureIndex(
  180. { expiresAt: 1 },
  181. { expireAfterSeconds: 0, background: true }
  182. )
  183. // For finding packs to be checked for archiving
  184. db.docHistory.ensureIndex({ last_checked: 1 }, { background: true })
  185. // For finding archived packs
  186. return db.docHistoryIndex.ensureIndex(
  187. { project_id: 1 },
  188. { background: true }
  189. )
  190. },
  191. }
  192. ;['getLastCompressedUpdate', 'getProjectMetaData', 'setProjectMetaData'].map(
  193. method =>
  194. metrics.timeAsyncMethod(MongoManager, method, 'mongo.MongoManager', logger)
  195. )