ProjectManager.coffee 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. RedisManager = require "./RedisManager"
  2. DocumentManager = require "./DocumentManager"
  3. async = require "async"
  4. logger = require "logger-sharelatex"
  5. Metrics = require "./Metrics"
  6. Errors = require "./Errors"
  7. module.exports = ProjectManager =
  8. flushProjectWithLocks: (project_id, _callback = (error) ->) ->
  9. timer = new Metrics.Timer("projectManager.flushProjectWithLocks")
  10. callback = (args...) ->
  11. timer.done()
  12. _callback(args...)
  13. RedisManager.getDocIdsInProject project_id, (error, doc_ids) ->
  14. return callback(error) if error?
  15. jobs = []
  16. errors = []
  17. for doc_id in (doc_ids or [])
  18. do (doc_id) ->
  19. jobs.push (callback) ->
  20. DocumentManager.flushDocIfLoadedWithLock project_id, doc_id, (error) ->
  21. if error? and error instanceof Errors.NotFoundError
  22. logger.warn err: error, project_id: project_id, doc_id: doc_id, "found deleted doc when flushing"
  23. callback()
  24. else if error?
  25. logger.error err: error, project_id: project_id, doc_id: doc_id, "error flushing doc"
  26. errors.push(error)
  27. callback()
  28. else
  29. callback()
  30. logger.log project_id: project_id, doc_ids: doc_ids, "flushing docs"
  31. async.series jobs, () ->
  32. if errors.length > 0
  33. callback new Error("Errors flushing docs. See log for details")
  34. else
  35. callback(null)
  36. flushAndDeleteProjectWithLocks: (project_id, _callback = (error) ->) ->
  37. timer = new Metrics.Timer("projectManager.flushAndDeleteProjectWithLocks")
  38. callback = (args...) ->
  39. timer.done()
  40. _callback(args...)
  41. RedisManager.getDocIdsInProject project_id, (error, doc_ids) ->
  42. return callback(error) if error?
  43. jobs = []
  44. errors = []
  45. for doc_id in (doc_ids or [])
  46. do (doc_id) ->
  47. jobs.push (callback) ->
  48. DocumentManager.flushAndDeleteDocWithLock project_id, doc_id, (error) ->
  49. if error?
  50. logger.error err: error, project_id: project_id, doc_id: doc_id, "error deleting doc"
  51. errors.push(error)
  52. callback()
  53. logger.log project_id: project_id, doc_ids: doc_ids, "deleting docs"
  54. async.series jobs, () ->
  55. if errors.length > 0
  56. callback new Error("Errors deleting docs. See log for details")
  57. else
  58. callback(null)
  59. getProjectDocsAndFlushIfOld: (project_id, projectStateHash, excludeVersions = {}, _callback = (error, docs) ->) ->
  60. timer = new Metrics.Timer("projectManager.getProjectDocsAndFlushIfOld")
  61. callback = (args...) ->
  62. timer.done()
  63. _callback(args...)
  64. RedisManager.checkOrSetProjectState project_id, projectStateHash, (error, projectStateChanged) ->
  65. if error?
  66. logger.error err: error, project_id: project_id, "error getting/setting project state in getProjectDocsAndFlushIfOld"
  67. return callback(error)
  68. # we can't return docs if project structure has changed
  69. if projectStateChanged
  70. return callback Errors.ProjectStateChangedError("project state changed")
  71. # project structure hasn't changed, return doc content from redis
  72. RedisManager.getDocIdsInProject project_id, (error, doc_ids) ->
  73. if error?
  74. logger.error err: error, project_id: project_id, "error getting doc ids in getProjectDocs"
  75. return callback(error)
  76. jobs = []
  77. for doc_id in doc_ids or []
  78. do (doc_id) ->
  79. jobs.push (cb) ->
  80. # get the doc lines from redis
  81. DocumentManager.getDocAndFlushIfOldWithLock project_id, doc_id, (err, lines, version) ->
  82. if err?
  83. logger.error err:err, project_id: project_id, doc_id: doc_id, "error getting project doc lines in getProjectDocsAndFlushIfOld"
  84. return cb(err)
  85. doc = {_id:doc_id, lines:lines, v:version} # create a doc object to return
  86. cb(null, doc)
  87. async.series jobs, (error, docs) ->
  88. return callback(error) if error?
  89. callback(null, docs)
  90. clearProjectState: (project_id, callback = (error) ->) ->
  91. RedisManager.clearProjectState project_id, callback
  92. updateProjectWithLocks: (project_id, user_id, docUpdates, fileUpdates, _callback = (error) ->) ->
  93. timer = new Metrics.Timer("projectManager.updateProject")
  94. callback = (args...) ->
  95. timer.done()
  96. _callback(args...)
  97. handleDocUpdate = (update, cb) ->
  98. doc_id = update.id
  99. if update.docLines?
  100. RedisManager.addEntity project_id, 'doc', doc_id, user_id, update, cb
  101. else
  102. DocumentManager.renameDocWithLock project_id, doc_id, user_id, update, cb
  103. handleFileUpdate = (update, cb) ->
  104. file_id = update.id
  105. if update.url?
  106. RedisManager.addEntity project_id, 'file', file_id, user_id, update, cb
  107. else
  108. RedisManager.renameFile project_id, file_id, user_id, update, cb
  109. async.each docUpdates, handleDocUpdate, (error) ->
  110. return callback(error) if error?
  111. async.each fileUpdates, handleFileUpdate, callback