MongoManager.js 5.5 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(doc_id, function (
  52. error,
  53. update
  54. ) {
  55. if (error != null) {
  56. return callback(error)
  57. }
  58. if (update != null) {
  59. if (update.broken) {
  60. // marked as broken so we will force a new op
  61. return callback(null, null)
  62. } else if (update.pack != null) {
  63. if (update.finalised) {
  64. // no more ops can be appended
  65. return callback(
  66. null,
  67. null,
  68. update.pack[0] != null ? update.pack[0].v : undefined
  69. )
  70. } else {
  71. return callback(
  72. null,
  73. update,
  74. update.pack[0] != null ? update.pack[0].v : undefined
  75. )
  76. }
  77. } else {
  78. return callback(null, update, update.v)
  79. }
  80. } else {
  81. return PackManager.getLastPackFromIndex(doc_id, function (error, pack) {
  82. if (error != null) {
  83. return callback(error)
  84. }
  85. if (
  86. (pack != null ? pack.inS3 : undefined) != null &&
  87. (pack != null ? pack.v_end : undefined) != null
  88. ) {
  89. return callback(null, null, pack.v_end)
  90. }
  91. return callback(null, null)
  92. })
  93. }
  94. })
  95. },
  96. backportProjectId(project_id, doc_id, callback) {
  97. if (callback == null) {
  98. callback = function (error) {}
  99. }
  100. return db.docHistory.updateMany(
  101. {
  102. doc_id: ObjectId(doc_id.toString()),
  103. project_id: { $exists: false }
  104. },
  105. {
  106. $set: { project_id: ObjectId(project_id.toString()) }
  107. },
  108. callback
  109. )
  110. },
  111. getProjectMetaData(project_id, callback) {
  112. if (callback == null) {
  113. callback = function (error, metadata) {}
  114. }
  115. return db.projectHistoryMetaData.findOne(
  116. {
  117. project_id: ObjectId(project_id.toString())
  118. },
  119. callback
  120. )
  121. },
  122. setProjectMetaData(project_id, metadata, callback) {
  123. if (callback == null) {
  124. callback = function (error) {}
  125. }
  126. return db.projectHistoryMetaData.updateOne(
  127. {
  128. project_id: ObjectId(project_id)
  129. },
  130. {
  131. $set: metadata
  132. },
  133. {
  134. upsert: true
  135. },
  136. callback
  137. )
  138. },
  139. upgradeHistory(project_id, callback) {
  140. // preserve the project's existing history
  141. if (callback == null) {
  142. callback = function (error) {}
  143. }
  144. return db.docHistory.updateMany(
  145. {
  146. project_id: ObjectId(project_id),
  147. temporary: true,
  148. expiresAt: { $exists: true }
  149. },
  150. {
  151. $set: { temporary: false },
  152. $unset: { expiresAt: '' }
  153. },
  154. callback
  155. )
  156. },
  157. ensureIndices() {
  158. // For finding all updates that go into a diff for a doc
  159. db.docHistory.ensureIndex({ doc_id: 1, v: 1 }, { background: true })
  160. // For finding all updates that affect a project
  161. db.docHistory.ensureIndex(
  162. { project_id: 1, 'meta.end_ts': 1 },
  163. { background: true }
  164. )
  165. // For finding updates that don't yet have a project_id and need it inserting
  166. db.docHistory.ensureIndex(
  167. { doc_id: 1, project_id: 1 },
  168. { background: true }
  169. )
  170. // For finding project meta-data
  171. db.projectHistoryMetaData.ensureIndex(
  172. { project_id: 1 },
  173. { background: true }
  174. )
  175. // TTL index for auto deleting week old temporary ops
  176. db.docHistory.ensureIndex(
  177. { expiresAt: 1 },
  178. { expireAfterSeconds: 0, background: true }
  179. )
  180. // For finding packs to be checked for archiving
  181. db.docHistory.ensureIndex({ last_checked: 1 }, { background: true })
  182. // For finding archived packs
  183. return db.docHistoryIndex.ensureIndex(
  184. { project_id: 1 },
  185. { background: true }
  186. )
  187. }
  188. }
  189. ;[
  190. 'getLastCompressedUpdate',
  191. 'getProjectMetaData',
  192. 'setProjectMetaData'
  193. ].map((method) =>
  194. metrics.timeAsyncMethod(MongoManager, method, 'mongo.MongoManager', logger)
  195. )