improve error handling of releaseLock

ported from docupdater
This commit is contained in:
Brian Gough 2017-03-31 15:17:13 +01:00
parent 5989d8f27f
commit b0b05d1e1b
2 changed files with 30 additions and 1 deletions

View file

@ -3,6 +3,7 @@ redis = require("redis-sharelatex")
rclient = redis.createClient(Settings.redis.web) rclient = redis.createClient(Settings.redis.web)
os = require "os" os = require "os"
crypto = require "crypto" crypto = require "crypto"
logger = require "logger-sharelatex"
HOST = os.hostname() HOST = os.hostname()
PID = process.pid PID = process.pid
@ -57,7 +58,13 @@ module.exports = LockManager =
callback err, true callback err, true
releaseLock: (key, lockValue, callback) -> releaseLock: (key, lockValue, callback) ->
rclient.eval LockManager.unlockScript, 1, key, lockValue, callback rclient.eval LockManager.unlockScript, 1, key, lockValue, (err, result) ->
if err?
return callback(err)
if result? and result isnt 1 # successful unlock should release exactly one key
logger.error {key:key, lockValue:lockValue, redis_err:err, redis_result:result}, "unlocking error"
return callback(new Error("tried to release timed out lock"))
callback(err,result)
runWithLock: (key, runner = ( (releaseLock = (error) ->) -> ), callback = ( (error) -> )) -> runWithLock: (key, runner = ( (releaseLock = (error) ->) -> ), callback = ( (error) -> )) ->
LockManager.getLock key, (error, lockValue) -> LockManager.getLock key, (error, lockValue) ->

View file

@ -15,6 +15,7 @@ describe "LockManager", ->
createClient: () => @rclient = createClient: () => @rclient =
auth: sinon.stub() auth: sinon.stub()
"settings-sharelatex": @Settings "settings-sharelatex": @Settings
"logger-sharelatex": {error: ->}
@key = "lock-key" @key = "lock-key"
@callback = sinon.stub() @callback = sinon.stub()
@ -174,3 +175,24 @@ describe "LockManager", ->
it "should call the callback with the error", -> it "should call the callback with the error", ->
@callback.calledWith(@error).should.equal true @callback.calledWith(@error).should.equal true
describe "releaseLock", ->
describe "when the lock is current", ->
beforeEach ->
@rclient.eval = sinon.stub().yields(null, 1)
@LockManager.releaseLock @key, @lockValue, @callback
it 'should clear the data from redis', ->
@rclient.eval.calledWith(@LockManager.unlockScript, 1, @key, @lockValue).should.equal true
it 'should call the callback', ->
@callback.called.should.equal true
describe "when the lock has expired", ->
beforeEach ->
@rclient.eval = sinon.stub().yields(null, 0)
@LockManager.releaseLock @key, @lockValue, @callback
it 'should return an error if the lock has expired', ->
@callback.calledWith(new Error("tried to release timed out lock")).should.equal true