Просмотр исходного кода

Merge pull request #84 from overleaf/bg-skip-history-flush-on-realtime-shutdown

skip history flush when project is cleared by realtime shutdown
Brian Gough 7 лет назад
Родитель
Сommit
a9ba7937c5

+ 3 - 0
services/document-updater/app/coffee/HistoryManager.coffee

@@ -28,6 +28,9 @@ module.exports = HistoryManager =
 	# flush changes and callback (for when we need to know the queue is flushed)
 	flushProjectChanges: (project_id, options, callback = (error) ->) ->
 		return callback() if !Settings.apis?.project_history?.enabled
+		if options.skip_history_flush
+			logger.log {project_id}, "skipping flush of project history from realtime shutdown"
+			return callback()
 		url = "#{Settings.apis.project_history.url}/project/#{project_id}/flush"
 		qs = {}
 		qs.background = true if options.background # pass on the background flush option if present

+ 1 - 0
services/document-updater/app/coffee/HttpController.coffee

@@ -133,6 +133,7 @@ module.exports = HttpController =
 		timer = new Metrics.Timer("http.deleteProject")
 		options = {}
 		options.background = true if req.query?.background # allow non-urgent flushes to be queued
+		options.skip_history_flush = true if req.query?.shutdown # don't flush history when realtime shuts down
 		ProjectManager.flushAndDeleteProjectWithLocks project_id, options, (error) ->
 			timer.done()
 			return next(error) if error?

+ 44 - 5
services/document-updater/test/acceptance/coffee/DeletingAProjectTests.coffee

@@ -41,17 +41,15 @@ describe "Deleting a project", ->
 				version: doc.update.v
 			}
 
-		sinon.spy MockTrackChangesApi, "flushDoc"
-		sinon.spy MockProjectHistoryApi, "flushProject"
 		DocUpdaterApp.ensureRunning(done)
 
-	after ->
-		MockTrackChangesApi.flushDoc.restore()
-		MockProjectHistoryApi.flushProject.restore()
 
 	describe "with documents which have been updated", ->
 		before (done) ->
 			sinon.spy MockWebApi, "setDocument"
+			sinon.spy MockTrackChangesApi, "flushDoc"
+			sinon.spy MockProjectHistoryApi, "flushProject"
+
 			async.series @docs.map((doc) =>
 				(callback) =>
 					DocUpdaterClient.preloadDoc @project_id, doc.id, (error) =>
@@ -68,6 +66,8 @@ describe "Deleting a project", ->
 
 		after ->
 			MockWebApi.setDocument.restore()
+			MockTrackChangesApi.flushDoc.restore()
+			MockProjectHistoryApi.flushProject.restore()
 
 		it "should return a 204 status code", ->
 			@statusCode.should.equal 204
@@ -96,3 +96,42 @@ describe "Deleting a project", ->
 
 		it "should flush each doc in project history", ->
 			MockProjectHistoryApi.flushProject.calledWith(@project_id).should.equal true
+
+	describe "with the shutdown=true parameter from realtime", ->
+		before (done) ->
+			sinon.spy MockWebApi, "setDocument"
+			sinon.spy MockTrackChangesApi, "flushDoc"
+			sinon.spy MockProjectHistoryApi, "flushProject"
+
+			async.series @docs.map((doc) =>
+				(callback) =>
+					DocUpdaterClient.preloadDoc @project_id, doc.id, callback
+			), (error) =>
+				throw error if error?
+				setTimeout () =>
+					DocUpdaterClient.deleteProjectOnShutdown @project_id, (error, res, body) =>
+						@statusCode = res.statusCode
+						done()
+				, 200
+
+		after ->
+			MockWebApi.setDocument.restore()
+			MockTrackChangesApi.flushDoc.restore()
+			MockProjectHistoryApi.flushProject.restore()
+
+		it "should return a 204 status code", ->
+			@statusCode.should.equal 204
+
+		it "should send each document to the web api", ->
+			for doc in @docs
+				MockWebApi.setDocument
+					.calledWith(@project_id, doc.id, doc.updatedLines)
+					.should.equal true
+
+		it "should flush each doc in track changes", ->
+			for doc in @docs
+				MockTrackChangesApi.flushDoc.calledWith(doc.id).should.equal true
+
+		it "should not flush to project history", ->
+			MockProjectHistoryApi.flushProject.called.should.equal false
+

+ 3 - 0
services/document-updater/test/acceptance/coffee/helpers/DocUpdaterClient.coffee

@@ -75,6 +75,9 @@ module.exports = DocUpdaterClient =
 	deleteProject: (project_id, callback = () ->) ->
 		request.del "http://localhost:3003/project/#{project_id}", callback
 
+	deleteProjectOnShutdown: (project_id, callback = () ->) ->
+		request.del "http://localhost:3003/project/#{project_id}?background=true&shutdown=true", callback
+
 	acceptChange: (project_id, doc_id, change_id, callback = () ->) ->
 		request.post "http://localhost:3003/project/#{project_id}/doc/#{doc_id}/change/#{change_id}/accept", callback
 

+ 22 - 0
services/document-updater/test/unit/coffee/HistoryManager/HistoryManagerTests.coffee

@@ -46,6 +46,28 @@ describe "HistoryManager", ->
 				.calledWith({url: "#{@Settings.apis.project_history.url}/project/#{@project_id}/flush", qs:{background:true}})
 				.should.equal true
 
+	describe "flushProjectChanges", ->
+
+		describe "in the normal case", ->
+			beforeEach ->
+				@request.post = sinon.stub().callsArgWith(1, null, statusCode: 204)
+				@HistoryManager.flushProjectChanges @project_id, {background:true}
+
+			it "should send a request to the project history api", ->
+				@request.post
+					.calledWith({url: "#{@Settings.apis.project_history.url}/project/#{@project_id}/flush", qs:{background:true}})
+					.should.equal true
+
+		describe "with the skip_history_flush option", ->
+			beforeEach ->
+				@request.post = sinon.stub()
+				@HistoryManager.flushProjectChanges @project_id, {skip_history_flush:true}
+
+			it "should not send a request to the project history api", ->
+				@request.post
+					.called
+					.should.equal false
+
 	describe "recordAndFlushHistoryOps", ->
 		beforeEach ->
 			@ops = [ 'mock-ops' ]

+ 11 - 0
services/document-updater/test/unit/coffee/HttpController/HttpControllerTests.coffee

@@ -343,6 +343,17 @@ describe "HttpController", ->
 			it "should time the request", ->
 				@Metrics.Timer::done.called.should.equal true
 
+		describe "with the shutdown=true option from realtime", ->
+			beforeEach ->
+				@ProjectManager.flushAndDeleteProjectWithLocks = sinon.stub().callsArgWith(2)
+				@req.query = {background:true, shutdown:true}
+				@HttpController.deleteProject(@req, @res, @next)
+
+			it "should pass the skip_history_flush option when flushing the project", ->
+				@ProjectManager.flushAndDeleteProjectWithLocks
+					.calledWith(@project_id, {background:true, skip_history_flush:true})
+					.should.equal true
+
 		describe "when an errors occurs", ->
 			beforeEach ->
 				@ProjectManager.flushAndDeleteProjectWithLocks = sinon.stub().callsArgWith(2, new Error("oops"))