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

Merge pull request #12 from sharelatex/hof-version-entity-creation

version entity creation; Connects to sharelatex/web-sharelatex-internal#104
Hayden Faulds 9 лет назад
Родитель
Сommit
bd45fcb5f8

+ 8 - 2
services/document-updater/app/coffee/ProjectManager.coffee

@@ -102,11 +102,17 @@ module.exports = ProjectManager =
 
 		handleDocUpdate = (update, cb) ->
 			doc_id = update.id
-			DocumentManager.renameDocWithLock project_id, doc_id, user_id, update, cb
+			if update.docLines?
+				RedisManager.addEntity project_id, 'doc', doc_id, user_id, update, cb
+			else
+				DocumentManager.renameDocWithLock project_id, doc_id, user_id, update, cb
 
 		handleFileUpdate = (update, cb) ->
 			file_id = update.id
-			RedisManager.renameFile project_id, file_id, user_id, update, cb
+			if update.url?
+				RedisManager.addEntity project_id, 'file', file_id, user_id, update, cb
+			else
+				RedisManager.renameFile project_id, file_id, user_id, update, cb
 
 		async.each docUpdates, handleDocUpdate, (error) ->
 			return callback(error) if error?

+ 15 - 0
services/document-updater/app/coffee/RedisManager.coffee

@@ -300,6 +300,21 @@ module.exports = RedisManager =
 
 		rclient.rpush projectHistoryKeys.projectHistoryOps({project_id}), jsonUpdate, callback
 
+	addEntity: (project_id, entity_type, entitiy_id, user_id, update, callback = (error) ->) ->
+		update =
+			pathname: update.pathname
+			docLines: update.docLines
+			url: update.url
+			meta:
+				user_id: user_id
+				ts: new Date()
+		update[entity_type] = entitiy_id
+
+		logger.log {project_id, update}, "queue add operation to project-history"
+		jsonUpdate = JSON.stringify(update)
+
+		rclient.rpush projectHistoryKeys.projectHistoryOps({project_id}), jsonUpdate, callback
+
 	clearUnflushedTime: (doc_id, callback = (error) ->) ->
 		rclient.del keys.unflushedTime(doc_id:doc_id), callback
 

+ 54 - 3
services/document-updater/test/acceptance/coffee/ApplyingUpdatesToProjectStructureTests.coffee

@@ -24,7 +24,7 @@ describe "Applying updates to a project's structure", ->
 				throw error if error?
 				setTimeout done, 200
 
-		it "should push the applied file renames to the project history changes api", (done) ->
+		it "should push the applied file renames to the project history api", (done) ->
 			rclient_history.lrange ProjectHistoryKeys.projectHistoryOps({@project_id}), 0, -1, (error, updates) =>
 				throw error if error?
 
@@ -52,7 +52,7 @@ describe "Applying updates to a project's structure", ->
 					throw error if error?
 					setTimeout done, 200
 
-			it "should push the applied doc renames to the project history changes api", (done) ->
+			it "should push the applied doc renames to the project history api", (done) ->
 				rclient_history.lrange ProjectHistoryKeys.projectHistoryOps({@project_id}), 0, -1, (error, updates) =>
 					throw error if error?
 
@@ -84,7 +84,7 @@ describe "Applying updates to a project's structure", ->
 					doc.pathname.should.equal @docUpdate.newPathname
 					done()
 
-			it "should push the applied doc renames to the project history changes api", (done) ->
+			it "should push the applied doc renames to the project history api", (done) ->
 				rclient_history.lrange ProjectHistoryKeys.projectHistoryOps({@project_id}), 0, -1, (error, updates) =>
 					throw error if error?
 
@@ -96,3 +96,54 @@ describe "Applying updates to a project's structure", ->
 					update.meta.ts.should.be.a('string')
 
 					done()
+
+	describe "adding a file", ->
+		before (done) ->
+			@project_id = DocUpdaterClient.randomId()
+			@fileUpdate =
+				id: DocUpdaterClient.randomId()
+				pathname: '/file-path'
+				url: 'filestore.example.com'
+			@fileUpdates = [ @fileUpdate ]
+			DocUpdaterClient.sendProjectUpdate @project_id, @user_id, [], @fileUpdates, (error) ->
+				throw error if error?
+				setTimeout done, 200
+
+		it "should push the file addition to the project history api", (done) ->
+			rclient_history.lrange ProjectHistoryKeys.projectHistoryOps({@project_id}), 0, -1, (error, updates) =>
+				throw error if error?
+
+				update = JSON.parse(updates[0])
+				update.file.should.equal @fileUpdate.id
+				update.pathname.should.equal '/file-path'
+				update.url.should.equal 'filestore.example.com'
+				update.meta.user_id.should.equal @user_id
+				update.meta.ts.should.be.a('string')
+
+				done()
+
+	describe "adding a doc", ->
+		before (done) ->
+			@project_id = DocUpdaterClient.randomId()
+			@docUpdate =
+				id: DocUpdaterClient.randomId()
+				pathname: '/file-path'
+				docLines: 'a\nb'
+			@docUpdates = [ @docUpdate ]
+			DocUpdaterClient.sendProjectUpdate @project_id, @user_id, @docUpdates, [], (error) ->
+				throw error if error?
+				setTimeout done, 200
+
+		it "should push the doc addition to the project history api", (done) ->
+			rclient_history.lrange ProjectHistoryKeys.projectHistoryOps({@project_id}), 0, -1, (error, updates) =>
+				throw error if error?
+
+				update = JSON.parse(updates[0])
+				update.doc.should.equal @docUpdate.id
+				update.pathname.should.equal '/file-path'
+				update.docLines.should.equal 'a\nb'
+				update.meta.user_id.should.equal @user_id
+				update.meta.ts.should.be.a('string')
+
+				done()
+

+ 101 - 43
services/document-updater/test/unit/coffee/ProjectManager/updateProjectTests.coffee

@@ -19,55 +19,113 @@ describe "ProjectManager", ->
 		@callback = sinon.stub()
 
 	describe "updateProjectWithLocks", ->
-		beforeEach ->
-			@firstDocUpdate =
-				id: 1
-				update: 'foo'
-			@secondDocUpdate =
-				id: 2
-				update: 'bar'
-			@docUpdates = [ @firstDocUpdate, @secondDocUpdate ]
-			@firstFileUpdate =
-				id: 2
-				update: 'bar'
-			@fileUpdates = [ @firstFileUpdate ]
-			@DocumentManager.renameDocWithLock = sinon.stub().yields()
-			@RedisManager.renameFile = sinon.stub().yields()
-
-		describe "successfully", ->
+		describe "rename operations", ->
 			beforeEach ->
-				@ProjectManager.updateProjectWithLocks @project_id, @user_id, @docUpdates, @fileUpdates, @callback
+				@firstDocUpdate =
+					id: 1
+					pathname: 'foo'
+					newPathname: 'foo'
+				@secondDocUpdate =
+					id: 2
+					pathname: 'bar'
+					newPathname: 'bar2'
+				@docUpdates = [ @firstDocUpdate, @secondDocUpdate ]
+				@firstFileUpdate =
+					id: 2
+					pathname: 'bar'
+					newPathname: 'bar2'
+				@fileUpdates = [ @firstFileUpdate ]
+				@DocumentManager.renameDocWithLock = sinon.stub().yields()
+				@RedisManager.renameFile = sinon.stub().yields()
 
-			it "should rename the docs in the updates", ->
-				@DocumentManager.renameDocWithLock
-					.calledWith(@project_id, @firstDocUpdate.id, @user_id, @firstDocUpdate)
-					.should.equal true
-				@DocumentManager.renameDocWithLock
-					.calledWith(@project_id, @secondDocUpdate.id, @user_id, @secondDocUpdate)
-					.should.equal true
+			describe "successfully", ->
+				beforeEach ->
+					@ProjectManager.updateProjectWithLocks @project_id, @user_id, @docUpdates, @fileUpdates, @callback
 
-			it "should rename the files in the updates", ->
-				@RedisManager.renameFile
-					.calledWith(@project_id, @firstFileUpdate.id, @user_id, @firstFileUpdate)
-					.should.equal true
+				it "should rename the docs in the updates", ->
+					@DocumentManager.renameDocWithLock
+						.calledWith(@project_id, @firstDocUpdate.id, @user_id, @firstDocUpdate)
+						.should.equal true
+					@DocumentManager.renameDocWithLock
+						.calledWith(@project_id, @secondDocUpdate.id, @user_id, @secondDocUpdate)
+						.should.equal true
 
-			it "should call the callback", ->
-				@callback.called.should.equal true
+				it "should rename the files in the updates", ->
+					@RedisManager.renameFile
+						.calledWith(@project_id, @firstFileUpdate.id, @user_id, @firstFileUpdate)
+						.should.equal true
 
-		describe "when renaming a doc fails", ->
-			beforeEach ->
-				@error = new Error('error')
-				@DocumentManager.renameDocWithLock = sinon.stub().yields(@error)
-				@ProjectManager.updateProjectWithLocks @project_id, @user_id, @docUpdates, @fileUpdates, @callback
+				it "should call the callback", ->
+					@callback.called.should.equal true
+
+			describe "when renaming a doc fails", ->
+				beforeEach ->
+					@error = new Error('error')
+					@DocumentManager.renameDocWithLock = sinon.stub().yields(@error)
+					@ProjectManager.updateProjectWithLocks @project_id, @user_id, @docUpdates, @fileUpdates, @callback
+
+				it "should call the callback with the error", ->
+					@callback.calledWith(@error).should.equal true
 
-			it "should call the callback with the error", ->
-				@callback.calledWith(@error).should.equal true
+			describe "when renaming a file fails", ->
+				beforeEach ->
+					@error = new Error('error')
+					@RedisManager.renameFile = sinon.stub().yields(@error)
+					@ProjectManager.updateProjectWithLocks @project_id, @user_id, @docUpdates, @fileUpdates, @callback
 
-		describe "when renaming a file fails", ->
+				it "should call the callback with the error", ->
+					@callback.calledWith(@error).should.equal true
+
+		describe "add operations", ->
 			beforeEach ->
-				@error = new Error('error')
-				@RedisManager.renameFile = sinon.stub().yields(@error)
-				@ProjectManager.updateProjectWithLocks @project_id, @user_id, @docUpdates, @fileUpdates, @callback
+				@firstDocUpdate =
+					id: 1
+					docLines: "a\nb"
+				@secondDocUpdate =
+					id: 2
+					docLines: "a\nb"
+				@docUpdates = [ @firstDocUpdate, @secondDocUpdate ]
+				@firstFileUpdate =
+					id: 2
+					url: 'filestore.example.com/2'
+				@fileUpdates = [ @firstFileUpdate ]
+				@RedisManager.addEntity = sinon.stub().yields()
+
+			describe "successfully", ->
+				beforeEach ->
+					@ProjectManager.updateProjectWithLocks @project_id, @user_id, @docUpdates, @fileUpdates, @callback
+
+				it "should add the docs in the updates", ->
+					@RedisManager.addEntity
+						.calledWith(@project_id, 'doc', @firstDocUpdate.id, @user_id, @firstDocUpdate)
+						.should.equal true
+					@RedisManager.addEntity
+						.calledWith(@project_id, 'doc', @secondDocUpdate.id, @user_id, @secondDocUpdate)
+						.should.equal true
+
+				it "should add the files in the updates", ->
+					@RedisManager.addEntity
+						.calledWith(@project_id, 'file', @firstFileUpdate.id, @user_id, @firstFileUpdate)
+						.should.equal true
+
+				it "should call the callback", ->
+					@callback.called.should.equal true
+
+			describe "when adding a doc fails", ->
+				beforeEach ->
+					@error = new Error('error')
+					@RedisManager.addEntity = sinon.stub().yields(@error)
+					@ProjectManager.updateProjectWithLocks @project_id, @user_id, @docUpdates, @fileUpdates, @callback
+
+				it "should call the callback with the error", ->
+					@callback.calledWith(@error).should.equal true
+
+			describe "when adding a file fails", ->
+				beforeEach ->
+					@error = new Error('error')
+					@RedisManager.addEntity = sinon.stub().yields(@error)
+					@ProjectManager.updateProjectWithLocks @project_id, @user_id, @docUpdates, @fileUpdates, @callback
+
+				it "should call the callback with the error", ->
+					@callback.calledWith(@error).should.equal true
 
-			it "should call the callback with the error", ->
-				@callback.calledWith(@error).should.equal true

+ 27 - 0
services/document-updater/test/unit/coffee/RedisManager/RedisManagerTests.coffee

@@ -739,3 +739,30 @@ describe "RedisManager", ->
 			@rclient.rpush
 				.calledWith("ProjectHistory:Ops:#{@project_id}", JSON.stringify(update))
 				.should.equal true
+
+	describe "addEntity", ->
+		beforeEach (done) ->
+			@rclient.rpush = sinon.stub().yields()
+			@entity_id = 1234
+			@entity_type = 'type'
+
+			@update =
+				pathname: @pathname = '/old'
+				docLines: @docLines = 'a\nb'
+				url: @url = 'filestore.example.com'
+
+			@RedisManager.addEntity @project_id, @entity_type, @entity_id, @userId, @update, done
+
+		it "should queue an update", ->
+			update =
+				pathname: @pathname
+				docLines: @docLines
+				url: @url
+				meta:
+					user_id: @user_id
+					ts: new Date()
+			update[@entity_type] = @entity_id
+
+			@rclient.rpush
+				.calledWith("ProjectHistory:Ops:#{@project_id}", JSON.stringify(update))
+				.should.equal true