mirror of
https://github.com/overleaf/overleaf.git
synced 2025-04-09 00:52:32 +00:00
support forcing new compressed update in popLastCompressedUpdate
callback with a null update, passing the version as an additional argument
This commit is contained in:
parent
dc35ef5cda
commit
d6b827426c
4 changed files with 81 additions and 17 deletions
services/track-changes
app/coffee
test/unit/coffee
|
@ -20,13 +20,24 @@ module.exports = MongoManager =
|
|||
deleteCompressedUpdate: (id, callback = (error) ->) ->
|
||||
db.docHistory.remove({ _id: ObjectId(id.toString()) }, callback)
|
||||
|
||||
popLastCompressedUpdate: (doc_id, callback = (error, update) ->) ->
|
||||
popLastCompressedUpdate: (doc_id, callback = (error, update, version) ->) ->
|
||||
# under normal use we pass back the last update as
|
||||
# callback(null,update).
|
||||
#
|
||||
# when we have an existing last update but want to force a new one
|
||||
# to start, we pass it back as callback(null,null,version), just
|
||||
# giving the version so we can check consistency.
|
||||
MongoManager.getLastCompressedUpdate doc_id, (error, update) ->
|
||||
return callback(error) if error?
|
||||
if update?
|
||||
MongoManager.deleteCompressedUpdate update._id, (error) ->
|
||||
return callback(error) if error?
|
||||
callback null, update
|
||||
if update.inS3?
|
||||
# we want to force a new update, but ensure that it is
|
||||
# consistent with the version of the existing one in S3
|
||||
return callback null, null, update.v
|
||||
else
|
||||
MongoManager.deleteCompressedUpdate update._id, (error) ->
|
||||
return callback(error) if error?
|
||||
callback null, update
|
||||
else
|
||||
callback null, null
|
||||
|
||||
|
|
|
@ -7,7 +7,6 @@ UpdateTrimmer = require "./UpdateTrimmer"
|
|||
logger = require "logger-sharelatex"
|
||||
async = require "async"
|
||||
DocArchiveManager = require "./DocArchiveManager"
|
||||
_ = require "underscore"
|
||||
|
||||
module.exports = UpdatesManager =
|
||||
compressAndSaveRawUpdates: (project_id, doc_id, rawUpdates, temporary, callback = (error) ->) ->
|
||||
|
@ -15,27 +14,29 @@ module.exports = UpdatesManager =
|
|||
if length == 0
|
||||
return callback()
|
||||
|
||||
MongoManager.popLastCompressedUpdate doc_id, (error, lastCompressedUpdate) ->
|
||||
MongoManager.popLastCompressedUpdate doc_id, (error, lastCompressedUpdate, lastVersion = lastCompressedUpdate?.v) ->
|
||||
# lastCompressedUpdate may be null if we are forcing the start
|
||||
# of a new compressed update, in which case we have the
|
||||
# lastVersion to check consistency (defaults to lastCompressedUpdate.v)
|
||||
return callback(error) if error?
|
||||
|
||||
# Ensure that raw updates start where lastCompressedUpdate left off
|
||||
if lastCompressedUpdate?
|
||||
# Ensure that raw updates start where lastVersion left off
|
||||
if lastVersion?
|
||||
rawUpdates = rawUpdates.slice(0)
|
||||
while rawUpdates[0]? and rawUpdates[0].v <= lastCompressedUpdate.v
|
||||
while rawUpdates[0]? and rawUpdates[0].v <= lastVersion
|
||||
rawUpdates.shift()
|
||||
|
||||
if rawUpdates[0]? and rawUpdates[0].v != lastCompressedUpdate.v + 1
|
||||
error = new Error("Tried to apply raw op at version #{rawUpdates[0].v} to last compressed update with version #{lastCompressedUpdate.v}")
|
||||
if rawUpdates[0]? and rawUpdates[0].v != lastVersion + 1
|
||||
error = new Error("Tried to apply raw op at version #{rawUpdates[0].v} to last compressed update with version #{lastVersion}")
|
||||
logger.error err: error, doc_id: doc_id, project_id: project_id, "inconsistent doc versions"
|
||||
# Push the update back into Mongo - catching errors at this
|
||||
# Push the update back into Mongo - if it was present - catching errors at this
|
||||
# point is useless, we're already bailing
|
||||
MongoManager.insertCompressedUpdates project_id, doc_id, [lastCompressedUpdate], temporary, () ->
|
||||
return callback error
|
||||
if lastCompressedUpdate?
|
||||
MongoManager.insertCompressedUpdates project_id, doc_id, [lastCompressedUpdate], temporary, () ->
|
||||
return callback error
|
||||
return
|
||||
|
||||
compressedUpdates = UpdateCompressor.compressRawUpdates lastCompressedUpdate, rawUpdates
|
||||
if lastCompressedUpdate?.inS3? and not _.some(compressedUpdates, (update) -> update.inS3)
|
||||
compressedUpdates[compressedUpdates.length-1].inS3 = lastCompressedUpdate.inS3
|
||||
|
||||
MongoManager.insertCompressedUpdates project_id, doc_id, compressedUpdates, temporary,(error) ->
|
||||
return callback(error) if error?
|
||||
|
|
|
@ -104,6 +104,25 @@ describe "MongoManager", ->
|
|||
it "should call the callback with the update", ->
|
||||
@callback.calledWith(null, @update).should.equal true
|
||||
|
||||
describe "when there is a last update in S3", ->
|
||||
beforeEach ->
|
||||
@update = { _id: Object(), v: 12345, inS3: true }
|
||||
@MongoManager.getLastCompressedUpdate = sinon.stub().callsArgWith(1, null, @update)
|
||||
@MongoManager.deleteCompressedUpdate = sinon.stub()
|
||||
@MongoManager.popLastCompressedUpdate @doc_id, @callback
|
||||
|
||||
it "should get the last update", ->
|
||||
@MongoManager.getLastCompressedUpdate
|
||||
.calledWith(@doc_id)
|
||||
.should.equal true
|
||||
|
||||
it "should not try to delete the last update", ->
|
||||
@MongoManager.deleteCompressedUpdate.called.should.equal false
|
||||
|
||||
it "should call the callback with a null update and the correct version", ->
|
||||
@callback.calledWith(null, null, @update.v).should.equal true
|
||||
|
||||
|
||||
describe "insertCompressedUpdate", ->
|
||||
beforeEach ->
|
||||
@update = { op: "op", meta: "meta", v: "v"}
|
||||
|
@ -483,4 +502,4 @@ describe "MongoManager", ->
|
|||
.should.equal true
|
||||
|
||||
it "should call the callback", ->
|
||||
@callback.called.should.equal true
|
||||
@callback.called.should.equal true
|
||||
|
|
|
@ -122,6 +122,39 @@ describe "UpdatesManager", ->
|
|||
.calledWith(@project_id, @doc_id, [@lastCompressedUpdate], @temporary)
|
||||
.should.equal true
|
||||
|
||||
describe "when the raw ops need appending to existing history which is in S3", ->
|
||||
beforeEach ->
|
||||
@lastCompressedUpdate = null
|
||||
@lastVersion = 11
|
||||
@compressedUpdates = { v: 13, op: "compressed-op-12" }
|
||||
|
||||
@MongoManager.popLastCompressedUpdate = sinon.stub().callsArgWith(1, null, null, @lastVersion)
|
||||
@MongoManager.insertCompressedUpdates = sinon.stub().callsArg(4)
|
||||
@UpdateCompressor.compressRawUpdates = sinon.stub().returns(@compressedUpdates)
|
||||
|
||||
describe "when the raw ops start where the existing history ends", ->
|
||||
beforeEach ->
|
||||
@rawUpdates = [{ v: 12, op: "mock-op-12" }, { v: 13, op: "mock-op-13" }]
|
||||
@UpdatesManager.compressAndSaveRawUpdates @project_id, @doc_id, @rawUpdates, @temporary, @callback
|
||||
|
||||
it "should try to pop the last compressed op", ->
|
||||
@MongoManager.popLastCompressedUpdate
|
||||
.calledWith(@doc_id)
|
||||
.should.equal true
|
||||
|
||||
it "should compress the last compressed op and the raw ops", ->
|
||||
@UpdateCompressor.compressRawUpdates
|
||||
.calledWith(@lastCompressedUpdate, @rawUpdates)
|
||||
.should.equal true
|
||||
|
||||
it "should save the compressed ops", ->
|
||||
@MongoManager.insertCompressedUpdates
|
||||
.calledWith(@project_id, @doc_id, @compressedUpdates, @temporary)
|
||||
.should.equal true
|
||||
|
||||
it "should call the callback", ->
|
||||
@callback.called.should.equal true
|
||||
|
||||
describe "processUncompressedUpdates", ->
|
||||
beforeEach ->
|
||||
@UpdatesManager.compressAndSaveRawUpdates = sinon.stub().callsArgWith(4)
|
||||
|
|
Loading…
Add table
Reference in a new issue