MongoManager.js 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. /* eslint-disable
  2. camelcase,
  3. */
  4. // TODO: This file was created by bulk-decaffeinate.
  5. // Fix any style issues and re-enable lint.
  6. /*
  7. * decaffeinate suggestions:
  8. * DS102: Remove unnecessary code created because of implicit returns
  9. * DS207: Consider shorter variations of null checks
  10. * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
  11. */
  12. let MongoManager
  13. const { db, ObjectId } = require('./mongodb')
  14. const logger = require('logger-sharelatex')
  15. const metrics = require('@overleaf/metrics')
  16. const Settings = require('@overleaf/settings')
  17. const Errors = require('./Errors')
  18. const { promisify } = require('util')
  19. module.exports = MongoManager = {
  20. findDoc(project_id, doc_id, filter, callback) {
  21. if (callback == null) {
  22. callback = function () {}
  23. }
  24. db.docs.findOne(
  25. {
  26. _id: ObjectId(doc_id.toString()),
  27. project_id: ObjectId(project_id.toString()),
  28. },
  29. {
  30. projection: filter,
  31. },
  32. callback
  33. )
  34. },
  35. getProjectsDeletedDocs(project_id, filter, callback) {
  36. db.docs
  37. .find(
  38. {
  39. project_id: ObjectId(project_id.toString()),
  40. deleted: true,
  41. },
  42. {
  43. projection: filter,
  44. sort: { deletedAt: -1 },
  45. limit: Settings.max_deleted_docs,
  46. }
  47. )
  48. .toArray(callback)
  49. },
  50. getProjectsDocs(project_id, options, filter, callback) {
  51. const query = { project_id: ObjectId(project_id.toString()) }
  52. if (!options.include_deleted) {
  53. query.deleted = { $ne: true }
  54. }
  55. const queryOptions = {
  56. projection: filter,
  57. }
  58. if (options.limit) {
  59. queryOptions.limit = options.limit
  60. }
  61. db.docs.find(query, queryOptions).toArray(callback)
  62. },
  63. getArchivedProjectDocs(project_id, maxResults, callback) {
  64. const query = {
  65. project_id: ObjectId(project_id.toString()),
  66. inS3: true,
  67. }
  68. db.docs
  69. .find(query, { projection: { _id: 1 }, limit: maxResults })
  70. .toArray(callback)
  71. },
  72. getNonArchivedProjectDocs(project_id, maxResults, callback) {
  73. const query = {
  74. project_id: ObjectId(project_id.toString()),
  75. inS3: { $ne: true },
  76. }
  77. db.docs.find(query, { limit: maxResults }).toArray(callback)
  78. },
  79. getNonDeletedArchivedProjectDocs(project_id, maxResults, callback) {
  80. const query = {
  81. project_id: ObjectId(project_id.toString()),
  82. deleted: { $ne: true },
  83. inS3: true,
  84. }
  85. db.docs
  86. .find(query, { projection: { _id: 1 }, limit: maxResults })
  87. .toArray(callback)
  88. },
  89. upsertIntoDocCollection(project_id, doc_id, updates, callback) {
  90. const update = {
  91. $set: updates,
  92. $inc: {
  93. rev: 1,
  94. },
  95. $unset: {
  96. inS3: true,
  97. },
  98. }
  99. update.$set.project_id = ObjectId(project_id)
  100. db.docs.updateOne(
  101. { _id: ObjectId(doc_id) },
  102. update,
  103. { upsert: true },
  104. callback
  105. )
  106. },
  107. patchDoc(project_id, doc_id, meta, callback) {
  108. db.docs.updateOne(
  109. {
  110. _id: ObjectId(doc_id),
  111. project_id: ObjectId(project_id),
  112. },
  113. { $set: meta },
  114. callback
  115. )
  116. },
  117. markDocAsArchived(doc_id, rev, callback) {
  118. const update = {
  119. $set: {},
  120. $unset: {},
  121. }
  122. update.$set.inS3 = true
  123. update.$unset.lines = true
  124. update.$unset.ranges = true
  125. const query = {
  126. _id: doc_id,
  127. rev,
  128. }
  129. db.docs.updateOne(query, update, callback)
  130. },
  131. getDocVersion(doc_id, callback) {
  132. if (callback == null) {
  133. callback = function () {}
  134. }
  135. db.docOps.findOne(
  136. {
  137. doc_id: ObjectId(doc_id),
  138. },
  139. {
  140. projection: {
  141. version: 1,
  142. },
  143. },
  144. function (error, doc) {
  145. if (error != null) {
  146. return callback(error)
  147. }
  148. callback(null, (doc && doc.version) || 0)
  149. }
  150. )
  151. },
  152. setDocVersion(doc_id, version, callback) {
  153. if (callback == null) {
  154. callback = function () {}
  155. }
  156. db.docOps.updateOne(
  157. {
  158. doc_id: ObjectId(doc_id),
  159. },
  160. {
  161. $set: { version },
  162. },
  163. {
  164. upsert: true,
  165. },
  166. callback
  167. )
  168. },
  169. getDocRev(doc_id, callback) {
  170. db.docs.findOne(
  171. {
  172. _id: ObjectId(doc_id.toString()),
  173. },
  174. {
  175. projection: { rev: 1 },
  176. },
  177. function (err, doc) {
  178. if (err != null) {
  179. return callback(err)
  180. }
  181. callback(null, doc && doc.rev)
  182. }
  183. )
  184. },
  185. // Helper method to support optimistic locking. Call the provided method for
  186. // an existing doc and return the result if the rev in mongo is unchanged when
  187. // checked afterwards. If the rev has changed, return a DocModifiedError.
  188. withRevCheck(doc, method, callback) {
  189. method(doc._id, function (err, result) {
  190. if (err) return callback(err)
  191. MongoManager.getDocRev(doc._id, function (err, currentRev) {
  192. if (err) return callback(err)
  193. if (doc.rev !== currentRev) {
  194. return callback(
  195. new Errors.DocModifiedError('doc rev has changed', {
  196. doc_id: doc._id,
  197. rev: doc.rev,
  198. currentRev,
  199. })
  200. )
  201. }
  202. return callback(null, result)
  203. })
  204. })
  205. },
  206. destroyDoc(doc_id, callback) {
  207. db.docs.deleteOne(
  208. {
  209. _id: ObjectId(doc_id),
  210. },
  211. function (err) {
  212. if (err != null) {
  213. return callback(err)
  214. }
  215. db.docOps.deleteOne(
  216. {
  217. doc_id: ObjectId(doc_id),
  218. },
  219. callback
  220. )
  221. }
  222. )
  223. },
  224. }
  225. const methods = Object.getOwnPropertyNames(MongoManager)
  226. module.exports.promises = {}
  227. for (const method of methods) {
  228. metrics.timeAsyncMethod(MongoManager, method, 'mongo.MongoManager', logger)
  229. module.exports.promises[method] = promisify(module.exports[method])
  230. }