From b7de4c9c6c30543a77f0052cf7e8aab9ff1ffe9a Mon Sep 17 00:00:00 2001 From: James Allen Date: Wed, 19 Mar 2014 17:44:16 +0000 Subject: [PATCH] Implement project update getter methods --- .../app/coffee/DiffManager.coffee | 2 +- .../app/coffee/HttpController.coffee | 2 +- .../app/coffee/MongoManager.coffee | 19 ++++- .../app/coffee/UpdatesManager.coffee | 22 ++++-- .../DiffManager/DiffManagerTests.coffee | 4 +- .../HttpController/HttpControllerTests.coffee | 4 +- .../MongoManager/MongoManagerTests.coffee | 65 +++++++++++++++-- .../UpdatesManager/UpdatesManagerTests.coffee | 69 +++++++++++++++---- 8 files changed, 155 insertions(+), 32 deletions(-) diff --git a/services/track-changes/app/coffee/DiffManager.coffee b/services/track-changes/app/coffee/DiffManager.coffee index 43eddad85d..9183c8ecaa 100644 --- a/services/track-changes/app/coffee/DiffManager.coffee +++ b/services/track-changes/app/coffee/DiffManager.coffee @@ -5,7 +5,7 @@ logger = require "logger-sharelatex" module.exports = DiffManager = getLatestDocAndUpdates: (project_id, doc_id, fromVersion, toVersion, callback = (error, content, version, updates) ->) -> - UpdatesManager.getUpdatesWithUserInfo project_id, doc_id, from: fromVersion, to: toVersion, (error, updates) -> + UpdatesManager.getDocUpdatesWithUserInfo project_id, doc_id, from: fromVersion, to: toVersion, (error, updates) -> return callback(error) if error? DocumentUpdaterManager.getDocument project_id, doc_id, (error, content, version) -> return callback(error) if error? diff --git a/services/track-changes/app/coffee/HttpController.coffee b/services/track-changes/app/coffee/HttpController.coffee index 703c1254f1..66c2c294ad 100644 --- a/services/track-changes/app/coffee/HttpController.coffee +++ b/services/track-changes/app/coffee/HttpController.coffee @@ -39,7 +39,7 @@ module.exports = HttpController = if req.query.limit? limit = parseInt(req.query.limit, 10) - UpdatesManager.getSummarizedUpdates project_id, doc_id, to: to, limit: limit, (error, updates) -> + UpdatesManager.getSummarizedDocUpdates project_id, doc_id, to: to, limit: limit, (error, updates) -> return next(error) if error? res.send JSON.stringify updates: updates diff --git a/services/track-changes/app/coffee/MongoManager.coffee b/services/track-changes/app/coffee/MongoManager.coffee index a733d3946e..71f926a745 100644 --- a/services/track-changes/app/coffee/MongoManager.coffee +++ b/services/track-changes/app/coffee/MongoManager.coffee @@ -40,7 +40,7 @@ module.exports = MongoManager = v: update.v }, callback - getUpdates:(doc_id, options = {}, callback = (error, updates) ->) -> + getDocUpdates:(doc_id, options = {}, callback = (error, updates) ->) -> query = doc_id: ObjectId(doc_id.toString()) if options.from? @@ -59,6 +59,23 @@ module.exports = MongoManager = cursor.toArray callback + getProjectUpdates: (project_id, options = {}, callback = (error, updates) ->) -> + query = + project_id: ObjectId(project_id.toString()) + + if options.before? + query["meta.end_ts"] = { $lt: options.before } + + cursor = db.docHistory + .find( query ) + .sort( "meta.end_ts": -1 ) + + if options.limit? + cursor.limit(options.limit) + + cursor.toArray callback + ensureIndices: (callback = (error) ->) -> db.docHistory.ensureIndex { doc_id: 1, v: 1 }, callback + db.docHistory.ensureIndex { project_id: 1, "meta.end_ts": 1 }, callback diff --git a/services/track-changes/app/coffee/UpdatesManager.coffee b/services/track-changes/app/coffee/UpdatesManager.coffee index 0613a50800..9c63f47de8 100644 --- a/services/track-changes/app/coffee/UpdatesManager.coffee +++ b/services/track-changes/app/coffee/UpdatesManager.coffee @@ -64,19 +64,29 @@ module.exports = UpdatesManager = callback ) - getUpdates: (project_id, doc_id, options = {}, callback = (error, updates) ->) -> + getDocUpdates: (project_id, doc_id, options = {}, callback = (error, updates) ->) -> UpdatesManager.processUncompressedUpdatesWithLock project_id, doc_id, (error) -> return callback(error) if error? - MongoManager.getUpdates doc_id, options, callback + MongoManager.getDocUpdates doc_id, options, callback - getUpdatesWithUserInfo: (project_id, doc_id, options = {}, callback = (error, updates) ->) -> - UpdatesManager.getUpdates project_id, doc_id, options, (error, updates) -> + getDocUpdatesWithUserInfo: (project_id, doc_id, options = {}, callback = (error, updates) ->) -> + UpdatesManager.getDocUpdates project_id, doc_id, options, (error, updates) -> return callback(error) if error? UpdatesManager.fillUserInfo updates, (error, updates) -> return callback(error) if error? callback null, updates - getSummarizedUpdates: (project_id, doc_id, options = {}, callback = (error, updates) ->) -> + getProjectUpdates: (project_id, options = {}, callback = (error, updates) ->) -> + MongoManager.getProjectUpdates project_id, options, callback + + getProjectUpdatesWithUserInfo: (project_id, options = {}, callback = (error, updates) ->) -> + UpdatesManager.getProjectUpdates project_id, options, (error, updates) -> + return callback(error) if error? + UpdatesManager.fillUserInfo updates, (error, updates) -> + return callback(error) if error? + callback null, updates + + getSummarizedDocUpdates: (project_id, doc_id, options = {}, callback = (error, updates) ->) -> options.limit ||= 25 summarizedUpdates = [] to = options.to @@ -97,7 +107,7 @@ module.exports = UpdatesManager = to, desiredLength, callback = (error, summarizedUpdates, endOfDatabase) -> ) -> - UpdatesManager.getUpdatesWithUserInfo project_id, doc_id, { to: to, limit: 3 * desiredLength }, (error, updates) -> + UpdatesManager.getDocUpdatesWithUserInfo project_id, doc_id, { to: to, limit: 3 * desiredLength }, (error, updates) -> return callback(error) if error? if !updates? or updates.length == 0 endOfDatabase = true diff --git a/services/track-changes/test/unit/coffee/DiffManager/DiffManagerTests.coffee b/services/track-changes/test/unit/coffee/DiffManager/DiffManagerTests.coffee index c58d40068a..e3214a2f36 100644 --- a/services/track-changes/test/unit/coffee/DiffManager/DiffManagerTests.coffee +++ b/services/track-changes/test/unit/coffee/DiffManager/DiffManagerTests.coffee @@ -25,7 +25,7 @@ describe "DiffManager", -> @updates = [ "mock-update-1", "mock-update-2" ] @DocumentUpdaterManager.getDocument = sinon.stub().callsArgWith(2, null, @content, @version) - @UpdatesManager.getUpdatesWithUserInfo = sinon.stub().callsArgWith(3, null, @updates) + @UpdatesManager.getDocUpdatesWithUserInfo = sinon.stub().callsArgWith(3, null, @updates) @DiffManager.getLatestDocAndUpdates @project_id, @doc_id, @from, @to, @callback it "should get the latest version of the doc", -> @@ -34,7 +34,7 @@ describe "DiffManager", -> .should.equal true it "should get the latest updates", -> - @UpdatesManager.getUpdatesWithUserInfo + @UpdatesManager.getDocUpdatesWithUserInfo .calledWith(@project_id, @doc_id, from: @from, to: @to) .should.equal true diff --git a/services/track-changes/test/unit/coffee/HttpController/HttpControllerTests.coffee b/services/track-changes/test/unit/coffee/HttpController/HttpControllerTests.coffee index 55742d5115..4d15670653 100644 --- a/services/track-changes/test/unit/coffee/HttpController/HttpControllerTests.coffee +++ b/services/track-changes/test/unit/coffee/HttpController/HttpControllerTests.coffee @@ -76,11 +76,11 @@ describe "HttpController", -> @res = send: sinon.stub() @updates = ["mock-summarized-updates"] - @UpdatesManager.getSummarizedUpdates = sinon.stub().callsArgWith(3, null, @updates) + @UpdatesManager.getSummarizedDocUpdates = sinon.stub().callsArgWith(3, null, @updates) @HttpController.getUpdates @req, @res, @next it "should get the updates", -> - @UpdatesManager.getSummarizedUpdates + @UpdatesManager.getSummarizedDocUpdates .calledWith(@project_id, @doc_id, to: @to, limit: @limit) .should.equal true diff --git a/services/track-changes/test/unit/coffee/MongoManager/MongoManagerTests.coffee b/services/track-changes/test/unit/coffee/MongoManager/MongoManagerTests.coffee index 6c24f42e37..c5609994a1 100644 --- a/services/track-changes/test/unit/coffee/MongoManager/MongoManagerTests.coffee +++ b/services/track-changes/test/unit/coffee/MongoManager/MongoManagerTests.coffee @@ -134,7 +134,7 @@ describe "MongoManager", -> it "should call the callback", -> @callback.called.should.equal true - describe "getUpdates", -> + describe "getDocUpdates", -> beforeEach -> @updates = ["mock-update"] @db.docHistory = {} @@ -148,7 +148,7 @@ describe "MongoManager", -> describe "with a to version", -> beforeEach -> - @MongoManager.getUpdates @doc_id, from: @from, to: @to, @callback + @MongoManager.getDocUpdates @doc_id, from: @from, to: @to, @callback it "should find the all updates between the to and from versions", -> @db.docHistory.find @@ -172,7 +172,7 @@ describe "MongoManager", -> describe "without a to version", -> beforeEach -> - @MongoManager.getUpdates @doc_id, from: @from, @callback + @MongoManager.getDocUpdates @doc_id, from: @from, @callback it "should find the all updates after the from version", -> @db.docHistory.find @@ -187,7 +187,7 @@ describe "MongoManager", -> describe "with a limit", -> beforeEach -> - @MongoManager.getUpdates @doc_id, from: @from, limit: @limit = 10, @callback + @MongoManager.getDocUpdates @doc_id, from: @from, limit: @limit = 10, @callback it "should limit the results", -> @db.docHistory.limit @@ -195,3 +195,60 @@ describe "MongoManager", -> .should.equal true + describe "getDocUpdates", -> + beforeEach -> + @updates = ["mock-update"] + @db.docHistory = {} + @db.docHistory.find = sinon.stub().returns @db.docHistory + @db.docHistory.sort = sinon.stub().returns @db.docHistory + @db.docHistory.limit = sinon.stub().returns @db.docHistory + @db.docHistory.toArray = sinon.stub().callsArgWith(0, null, @updates) + + @before = Date.now() + + describe "with a before timestamp", -> + beforeEach -> + @MongoManager.getProjectUpdates @project_id, before: @before, @callback + + it "should find the all updates before the timestamp", -> + @db.docHistory.find + .calledWith({ + project_id: ObjectId(@project_id) + "meta.end_ts": { $lt: @before } + }) + .should.equal true + + it "should sort in descending version order", -> + @db.docHistory.sort + .calledWith("meta.end_ts": -1) + .should.equal true + + it "should not limit the results", -> + @db.docHistory.limit + .called.should.equal false + + it "should call the call back with the updates", -> + @callback.calledWith(null, @updates).should.equal true + + describe "without a before timestamp", -> + beforeEach -> + @MongoManager.getProjectUpdates @project_id, {}, @callback + + it "should find the all updates", -> + @db.docHistory.find + .calledWith({ + project_id: ObjectId(@project_id) + }) + .should.equal true + + it "should call the call back with the updates", -> + @callback.calledWith(null, @updates).should.equal true + + describe "with a limit", -> + beforeEach -> + @MongoManager.getProjectUpdates @project_id, before: @before, limit: @limit = 10, @callback + + it "should limit the results", -> + @db.docHistory.limit + .calledWith(@limit) + .should.equal true diff --git a/services/track-changes/test/unit/coffee/UpdatesManager/UpdatesManagerTests.coffee b/services/track-changes/test/unit/coffee/UpdatesManager/UpdatesManagerTests.coffee index 60611d8907..0673a08c8f 100644 --- a/services/track-changes/test/unit/coffee/UpdatesManager/UpdatesManagerTests.coffee +++ b/services/track-changes/test/unit/coffee/UpdatesManager/UpdatesManagerTests.coffee @@ -198,13 +198,13 @@ describe "UpdatesManager", -> it "should call the callback", -> @callback.called.should.equal true - describe "getUpdates", -> + describe "getDocUpdates", -> beforeEach -> @updates = ["mock-updates"] @options = { to: "mock-to", limit: "mock-limit" } - @MongoManager.getUpdates = sinon.stub().callsArgWith(2, null, @updates) + @MongoManager.getDocUpdates = sinon.stub().callsArgWith(2, null, @updates) @UpdatesManager.processUncompressedUpdatesWithLock = sinon.stub().callsArg(2) - @UpdatesManager.getUpdates @project_id, @doc_id, @options, @callback + @UpdatesManager.getDocUpdates @project_id, @doc_id, @options, @callback it "should process outstanding updates", -> @UpdatesManager.processUncompressedUpdatesWithLock @@ -212,7 +212,7 @@ describe "UpdatesManager", -> .should.equal true it "should get the updates from the database", -> - @MongoManager.getUpdates + @MongoManager.getDocUpdates .calledWith(@doc_id, @options) .should.equal true @@ -221,17 +221,17 @@ describe "UpdatesManager", -> .calledWith(null, @updates) .should.equal true - describe "getUpdatesWithUserInfo", -> + describe "getDocUpdatesWithUserInfo", -> beforeEach -> @updates = ["mock-updates"] @options = { to: "mock-to", limit: "mock-limit" } @updatesWithUserInfo = ["updates-with-user-info"] - @UpdatesManager.getUpdates = sinon.stub().callsArgWith(3, null, @updates) + @UpdatesManager.getDocUpdates = sinon.stub().callsArgWith(3, null, @updates) @UpdatesManager.fillUserInfo = sinon.stub().callsArgWith(1, null, @updatesWithUserInfo) - @UpdatesManager.getUpdatesWithUserInfo @project_id, @doc_id, @options, @callback + @UpdatesManager.getDocUpdatesWithUserInfo @project_id, @doc_id, @options, @callback it "should get the updates", -> - @UpdatesManager.getUpdates + @UpdatesManager.getDocUpdates .calledWith(@project_id, @doc_id, @options) .should.equal true @@ -243,6 +243,45 @@ describe "UpdatesManager", -> it "should return the updates with the filled details", -> @callback.calledWith(null, @updatesWithUserInfo).should.equal true + describe "getProjectUpdates", -> + beforeEach -> + @updates = ["mock-updates"] + @options = { before: "mock-before", limit: "mock-limit" } + @MongoManager.getProjectUpdates = sinon.stub().callsArgWith(2, null, @updates) + @UpdatesManager.getProjectUpdates @project_id, @options, @callback + + it "should get the updates from the database", -> + @MongoManager.getProjectUpdates + .calledWith(@project_id, @options) + .should.equal true + + it "should return the updates", -> + @callback + .calledWith(null, @updates) + .should.equal true + + describe "getProjectUpdatesWithUserInfo", -> + beforeEach -> + @updates = ["mock-updates"] + @options = { before: "mock-before", limit: "mock-limit" } + @updatesWithUserInfo = ["updates-with-user-info"] + @UpdatesManager.getProjectUpdates = sinon.stub().callsArgWith(2, null, @updates) + @UpdatesManager.fillUserInfo = sinon.stub().callsArgWith(1, null, @updatesWithUserInfo) + @UpdatesManager.getProjectUpdatesWithUserInfo @project_id, @options, @callback + + it "should get the updates", -> + @UpdatesManager.getProjectUpdates + .calledWith(@project_id, @options) + .should.equal true + + it "should file the updates with the user info", -> + @UpdatesManager.fillUserInfo + .calledWith(@updates) + .should.equal true + + it "should return the updates with the filled details", -> + @callback.calledWith(null, @updatesWithUserInfo).should.equal true + describe "_extendBatchOfSummarizedUpdates", -> beforeEach -> @to = 42 @@ -256,11 +295,11 @@ describe "UpdatesManager", -> @existingSummarizedUpdates = ["summarized-updates-3"] @summarizedUpdates = ["summarized-updates-3", "summarized-update-2", "summarized-update-1"] @UpdatesManager._summarizeUpdates = sinon.stub().returns(@summarizedUpdates) - @UpdatesManager.getUpdatesWithUserInfo = sinon.stub().callsArgWith(3, null, @updates) + @UpdatesManager.getDocUpdatesWithUserInfo = sinon.stub().callsArgWith(3, null, @updates) @UpdatesManager._extendBatchOfSummarizedUpdates @project_id, @doc_id, @existingSummarizedUpdates, @to, @limit, @callback it "should get the updates", -> - @UpdatesManager.getUpdatesWithUserInfo + @UpdatesManager.getDocUpdatesWithUserInfo .calledWith(@project_id, @doc_id, { to: @to, limit: 3 * @limit }) .should.equal true @@ -276,20 +315,20 @@ describe "UpdatesManager", -> beforeEach -> @updates = [] @UpdatesManager._summarizeUpdates = sinon.stub().returns(@summarizedUpdates) - @UpdatesManager.getUpdatesWithUserInfo = sinon.stub().callsArgWith(3, null, @updates) + @UpdatesManager.getDocUpdatesWithUserInfo = sinon.stub().callsArgWith(3, null, @updates) @UpdatesManager._extendBatchOfSummarizedUpdates @project_id, @doc_id, @existingSummarizedUpdates, @to, @limit, @callback it "should call the callback with the summarized updates and true for end-of-database", -> @callback.calledWith(null, @summarizedUpdates.slice(0, @limit), true).should.equal true - describe "getSummarizedUpdates", -> + describe "getSummarizedDocUpdates", -> describe "when one batch of updates is enough to meet the limit", -> beforeEach -> @to = 42 @limit = 2 @updates = ["summarized-updates-3", "summarized-updates-2"] @UpdatesManager._extendBatchOfSummarizedUpdates = sinon.stub().callsArgWith(5, null, @updates) - @UpdatesManager.getSummarizedUpdates @project_id, @doc_id, { to: @to, limit: @limit }, @callback + @UpdatesManager.getSummarizedDocUpdates @project_id, @doc_id, { to: @to, limit: @limit }, @callback it "should get the batch of summarized updates", -> @UpdatesManager._extendBatchOfSummarizedUpdates @@ -311,7 +350,7 @@ describe "UpdatesManager", -> else callback null, @firstBatch.concat(@secondBatch), false sinon.spy @UpdatesManager, "_extendBatchOfSummarizedUpdates" - @UpdatesManager.getSummarizedUpdates @project_id, @doc_id, { to: @to, limit: @limit }, @callback + @UpdatesManager.getSummarizedDocUpdates @project_id, @doc_id, { to: @to, limit: @limit }, @callback it "should get the first batch of summarized updates", -> @UpdatesManager._extendBatchOfSummarizedUpdates @@ -332,7 +371,7 @@ describe "UpdatesManager", -> @limit = 4 @updates = [{ toV: 6, fromV: 6 }, { toV: 5, fromV: 5 }] @UpdatesManager._extendBatchOfSummarizedUpdates = sinon.stub().callsArgWith(5, null, @updates, true) - @UpdatesManager.getSummarizedUpdates @project_id, @doc_id, { to: @to, limit: @limit }, @callback + @UpdatesManager.getSummarizedDocUpdates @project_id, @doc_id, { to: @to, limit: @limit }, @callback it "should get the batch of summarized updates", -> @UpdatesManager._extendBatchOfSummarizedUpdates