Преглед изворни кода

make history update more atomic

Brian Gough пре 9 година
родитељ
комит
79d8fced49

+ 5 - 9
services/document-updater/app/coffee/HistoryRedisManager.coffee

@@ -8,13 +8,9 @@ module.exports = HistoryRedisManager =
 	pushUncompressedHistoryOps: (project_id, doc_id, ops = [], callback = (error, length) ->) ->
 		if ops.length == 0
 			return callback(new Error("cannot push no ops")) # This should never be called with no ops, but protect against a redis error if we sent an empty array to rpush
-		opVersions = ops.map (op) -> op?.v
-		logger.log project_id: project_id, doc_id: doc_id, op_versions: opVersions, "pushing uncompressed history ops"
-		jsonOps = ops.map (op) -> JSON.stringify op
-		async.parallel [
-			(cb) -> rclient.rpush Keys.uncompressedHistoryOps({doc_id}), jsonOps..., cb
-			(cb) -> rclient.sadd Keys.docsWithHistoryOps({project_id}), doc_id, cb
-		], (error, results) ->
+		logger.log project_id: project_id, doc_id: doc_id, "marking doc in project for history ops"
+		rclient.sadd Keys.docsWithHistoryOps({project_id}), doc_id, (error) ->
 			return callback(error) if error?
-			[length, _] = results
-			callback(error, length)
+			rclient.llen Keys.uncompressedHistoryOps({doc_id}), (error, length) ->
+				return callback(error) if error?
+				callback(null, length)

+ 6 - 3
services/document-updater/app/coffee/RedisManager.coffee

@@ -25,6 +25,7 @@ MEGABYTES = 1024 * 1024
 MAX_RANGES_SIZE = 3 * MEGABYTES
 
 keys = Settings.redis.documentupdater.key_schema
+historyKeys = Settings.redis.history.key_schema
 
 module.exports = RedisManager =
 	rclient: rclient
@@ -167,9 +168,10 @@ module.exports = RedisManager =
 				logger.error err: error, doc_id: doc_id, newDocLines: newDocLines, error.message
 				return callback(error)
 			newHash = RedisManager._computeHash(newDocLines)
-			
-			logger.log doc_id: doc_id, version: newVersion, hash: newHash, "updating doc in redis"
-			
+
+			opVersions = appliedOps.map (op) -> op?.v
+			logger.log doc_id: doc_id, version: newVersion, hash: newHash, op_versions: opVersions, "updating doc in redis"
+
 			RedisManager._serializeRanges ranges, (error, ranges) ->
 				if error?
 					logger.error {err: error, doc_id}, error.message
@@ -180,6 +182,7 @@ module.exports = RedisManager =
 				multi.set    keys.docHash(doc_id:doc_id), newHash
 				if jsonOps.length > 0
 					multi.rpush  keys.docOps(doc_id: doc_id), jsonOps...
+					multi.rpush  historyKeys.uncompressedHistoryOps(doc_id: doc_id), jsonOps...
 				multi.expire keys.docOps(doc_id: doc_id), RedisManager.DOC_OPS_TTL
 				multi.ltrim  keys.docOps(doc_id: doc_id), -RedisManager.DOC_OPS_MAX_LENGTH, -1
 				if ranges?

+ 1 - 11
services/document-updater/test/unit/coffee/HistoryRedisManager/HistoryRedisManagerTests.coffee

@@ -27,7 +27,7 @@ describe "HistoryRedisManager", ->
 	describe "pushUncompressedHistoryOps", ->
 		beforeEach ->
 			@ops = [{ op: [{ i: "foo", p: 4 }] },{ op: [{ i: "bar", p: 56 }] }]
-			@rclient.rpush = sinon.stub().yields(null, @length = 42)
+			@rclient.llen = sinon.stub().yields(null, @length = 42)
 			@rclient.sadd = sinon.stub().yields()
 		
 		describe "with ops", ->
@@ -36,11 +36,6 @@ describe "HistoryRedisManager", ->
 					@callback(args...)
 					done()
 			
-			it "should push the doc op into the doc ops list as JSON", ->
-				@rclient.rpush
-					.calledWith("UncompressedHistoryOps:#{@doc_id}", JSON.stringify(@ops[0]), JSON.stringify(@ops[1]))
-					.should.equal true
-
 			it "should add the doc_id to the set of which records the project docs", ->
 				@rclient.sadd
 					.calledWith("DocsWithHistoryOps:#{@project_id}", @doc_id)
@@ -55,11 +50,6 @@ describe "HistoryRedisManager", ->
 					@callback(args...)
 					done()
 			
-			it "should not push the doc op into the doc ops list as JSON", ->
-				@rclient.rpush
-					.called
-					.should.equal false
-
 			it "should not add the doc_id to the set of which records the project docs", ->
 				@rclient.sadd
 					.called

+ 5 - 1
services/document-updater/test/unit/coffee/RedisManager/RedisManagerTests.coffee

@@ -19,7 +19,7 @@ describe "RedisManager", ->
 					documentupdater: {logHashErrors: {write:true, read:true}}
 					redis:
 						documentupdater:
-							key_schema: 
+							key_schema:
 								blockingKey: ({doc_id}) -> "Blocking:#{doc_id}"
 								docLines: ({doc_id}) -> "doclines:#{doc_id}"
 								docOps: ({doc_id}) -> "DocOps:#{doc_id}"
@@ -29,6 +29,10 @@ describe "RedisManager", ->
 								pendingUpdates: ({doc_id}) -> "PendingUpdates:#{doc_id}"
 								docsInProject: ({project_id}) -> "DocsIn:#{project_id}"
 								ranges: ({doc_id}) -> "Ranges:#{doc_id}"
+						history:
+							key_schema:
+								uncompressedHistoryOps: ({doc_id}) -> "UncompressedHistoryOps:#{doc_id}"
+								docsWithHistoryOps: ({project_id}) -> "DocsWithHistoryOps:#{project_id}"
 				}
 				"redis-sharelatex":
 					createClient: () => @rclient