Wait for both backends to return so that they are always in sync

This commit is contained in:
James Allen 2016-07-05 16:07:47 +01:00
parent dfd45bd23c
commit e912ccc562

View file

@ -58,6 +58,8 @@ class MultiClient
constructor: (@clients) -> constructor: (@clients) ->
exec: (callback) -> exec: (callback) ->
primaryError = null
primaryResult = null
jobs = @clients.map (client) -> jobs = @clients.map (client) ->
(cb) -> (cb) ->
timer = new Metrics.Timer("redis.#{client.driver}.exec") timer = new Metrics.Timer("redis.#{client.driver}.exec")
@ -80,15 +82,15 @@ class MultiClient
result = filtered_result result = filtered_result
if client.primary if client.primary
# Return this result as the actual result primaryError = error
callback(error, result) primaryResult = result
# Send the rest through for comparison
cb(error, result) cb(error, result)
async.parallel jobs, (error, results) -> async.parallel jobs, (error, results) ->
if error? if error?
logger.error {err: error}, "error in redis backend" logger.error {err: error}, "error in redis backend"
else else
compareResults(results) compareResults(results)
callback(primaryError, primaryResult)
COMMANDS = { COMMANDS = {
"get": 0, "get": 0,
@ -108,6 +110,8 @@ COMMANDS = {
for command, key_pos of COMMANDS for command, key_pos of COMMANDS
do (command, key_pos) -> do (command, key_pos) ->
Client.prototype[command] = (args..., callback) -> Client.prototype[command] = (args..., callback) ->
primaryError = null
primaryResult = null
jobs = @clients.map (client) -> jobs = @clients.map (client) ->
(cb) -> (cb) ->
key_builder = args[key_pos] key_builder = args[key_pos]
@ -118,15 +122,15 @@ for command, key_pos of COMMANDS
client.rclient[command] args_with_key..., (error, result...) -> client.rclient[command] args_with_key..., (error, result...) ->
timer.done() timer.done()
if client.primary if client.primary
# Return this result as the actual result primaryError = error
callback(error, result...) primaryResult = result
# Send the rest through for comparison
cb(error, result...) cb(error, result...)
async.parallel jobs, (error, results) -> async.parallel jobs, (error, results) ->
if error? if error?
logger.error {err: error}, "error in redis backend" logger.error {err: error}, "error in redis backend"
else else
compareResults(results) compareResults(results)
callback(primaryError, primaryResult...)
MultiClient.prototype[command] = (args...) -> MultiClient.prototype[command] = (args...) ->
for client in @clients for client in @clients
@ -141,6 +145,7 @@ compareResults = (results) ->
first = results[0] first = results[0]
for result in results.slice(1) for result in results.slice(1)
if not _.isEqual(first, result) if not _.isEqual(first, result)
logger.error results: results, "redis backend conflict"
Metrics.inc "backend-conflict" Metrics.inc "backend-conflict"
else else
Metrics.inc "backend-match" Metrics.inc "backend-match"