DocumentManager.coffee 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. RedisManager = require "./RedisManager"
  2. PersistenceManager = require "./PersistenceManager"
  3. DiffCodec = require "./DiffCodec"
  4. logger = require "logger-sharelatex"
  5. Metrics = require "./Metrics"
  6. HistoryManager = require "./HistoryManager"
  7. WebRedisManager = require "./WebRedisManager"
  8. module.exports = DocumentManager =
  9. getDoc: (project_id, doc_id, _callback = (error, lines, version, alreadyLoaded) ->) ->
  10. timer = new Metrics.Timer("docManager.getDoc")
  11. callback = (args...) ->
  12. timer.done()
  13. _callback(args...)
  14. RedisManager.getDoc project_id, doc_id, (error, lines, version, track_changes_entries) ->
  15. return callback(error) if error?
  16. if !lines? or !version?
  17. logger.log {project_id, doc_id}, "doc not in redis so getting from persistence API"
  18. PersistenceManager.getDoc project_id, doc_id, (error, lines, version, track_changes_entries) ->
  19. return callback(error) if error?
  20. logger.log {project_id, doc_id, lines, version}, "got doc from persistence API"
  21. RedisManager.putDocInMemory project_id, doc_id, lines, version, track_changes_entries, (error) ->
  22. return callback(error) if error?
  23. callback null, lines, version, track_changes_entries, false
  24. else
  25. callback null, lines, version, track_changes_entries, true
  26. getDocAndRecentOps: (project_id, doc_id, fromVersion, _callback = (error, lines, version, recentOps) ->) ->
  27. timer = new Metrics.Timer("docManager.getDocAndRecentOps")
  28. callback = (args...) ->
  29. timer.done()
  30. _callback(args...)
  31. DocumentManager.getDoc project_id, doc_id, (error, lines, version) ->
  32. return callback(error) if error?
  33. if fromVersion == -1
  34. callback null, lines, version, []
  35. else
  36. RedisManager.getPreviousDocOps doc_id, fromVersion, version, (error, ops) ->
  37. return callback(error) if error?
  38. callback null, lines, version, ops
  39. setDoc: (project_id, doc_id, newLines, source, user_id, _callback = (error) ->) ->
  40. timer = new Metrics.Timer("docManager.setDoc")
  41. callback = (args...) ->
  42. timer.done()
  43. _callback(args...)
  44. if !newLines?
  45. return callback(new Error("No lines were provided to setDoc"))
  46. UpdateManager = require "./UpdateManager"
  47. DocumentManager.getDoc project_id, doc_id, (error, oldLines, version, track_changes, alreadyLoaded) ->
  48. return callback(error) if error?
  49. if oldLines? and oldLines.length > 0 and oldLines[0].text?
  50. logger.log doc_id: doc_id, project_id: project_id, oldLines: oldLines, newLines: newLines, "document is JSON so not updating"
  51. return callback(null)
  52. logger.log doc_id: doc_id, project_id: project_id, oldLines: oldLines, newLines: newLines, "setting a document via http"
  53. DiffCodec.diffAsShareJsOp oldLines, newLines, (error, op) ->
  54. return callback(error) if error?
  55. update =
  56. doc: doc_id
  57. op: op
  58. v: version
  59. meta:
  60. type: "external"
  61. source: source
  62. user_id: user_id
  63. UpdateManager.applyUpdate project_id, doc_id, update, (error) ->
  64. return callback(error) if error?
  65. # If the document was loaded already, then someone has it open
  66. # in a project, and the usual flushing mechanism will happen.
  67. # Otherwise we should remove it immediately since nothing else
  68. # is using it.
  69. if alreadyLoaded
  70. DocumentManager.flushDocIfLoaded project_id, doc_id, (error) ->
  71. return callback(error) if error?
  72. callback null
  73. else
  74. DocumentManager.flushAndDeleteDoc project_id, doc_id, (error) ->
  75. return callback(error) if error?
  76. callback null
  77. flushDocIfLoaded: (project_id, doc_id, _callback = (error) ->) ->
  78. timer = new Metrics.Timer("docManager.flushDocIfLoaded")
  79. callback = (args...) ->
  80. timer.done()
  81. _callback(args...)
  82. RedisManager.getDoc project_id, doc_id, (error, lines, version, track_changes_entries) ->
  83. return callback(error) if error?
  84. if !lines? or !version?
  85. logger.log project_id: project_id, doc_id: doc_id, "doc is not loaded so not flushing"
  86. callback null # TODO: return a flag to bail out, as we go on to remove doc from memory?
  87. else
  88. logger.log project_id: project_id, doc_id: doc_id, version: version, "flushing doc"
  89. PersistenceManager.setDoc project_id, doc_id, lines, version, track_changes_entries, (error) ->
  90. return callback(error) if error?
  91. callback null
  92. flushAndDeleteDoc: (project_id, doc_id, _callback = (error) ->) ->
  93. timer = new Metrics.Timer("docManager.flushAndDeleteDoc")
  94. callback = (args...) ->
  95. timer.done()
  96. _callback(args...)
  97. DocumentManager.flushDocIfLoaded project_id, doc_id, (error) ->
  98. return callback(error) if error?
  99. # Flush in the background since it requires and http request
  100. # to track changes
  101. HistoryManager.flushDocChanges project_id, doc_id, (err) ->
  102. if err?
  103. logger.err {err, project_id, doc_id}, "error flushing to track changes"
  104. RedisManager.removeDocFromMemory project_id, doc_id, (error) ->
  105. return callback(error) if error?
  106. callback null
  107. getDocWithLock: (project_id, doc_id, callback = (error, lines, version) ->) ->
  108. UpdateManager = require "./UpdateManager"
  109. UpdateManager.lockUpdatesAndDo DocumentManager.getDoc, project_id, doc_id, callback
  110. getDocAndRecentOpsWithLock: (project_id, doc_id, fromVersion, callback = (error, lines, version) ->) ->
  111. UpdateManager = require "./UpdateManager"
  112. UpdateManager.lockUpdatesAndDo DocumentManager.getDocAndRecentOps, project_id, doc_id, fromVersion, callback
  113. setDocWithLock: (project_id, doc_id, lines, source, user_id, callback = (error) ->) ->
  114. UpdateManager = require "./UpdateManager"
  115. UpdateManager.lockUpdatesAndDo DocumentManager.setDoc, project_id, doc_id, lines, source, user_id, callback
  116. flushDocIfLoadedWithLock: (project_id, doc_id, callback = (error) ->) ->
  117. UpdateManager = require "./UpdateManager"
  118. UpdateManager.lockUpdatesAndDo DocumentManager.flushDocIfLoaded, project_id, doc_id, callback
  119. flushAndDeleteDocWithLock: (project_id, doc_id, callback = (error) ->) ->
  120. UpdateManager = require "./UpdateManager"
  121. UpdateManager.lockUpdatesAndDo DocumentManager.flushAndDeleteDoc, project_id, doc_id, callback