LockManager.coffee 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455
  1. metrics = require('./Metrics')
  2. Settings = require('settings-sharelatex')
  3. redis = require('redis')
  4. redisConf = Settings.redis.web
  5. rclient = redis.createClient(redisConf.port, redisConf.host)
  6. rclient.auth(redisConf.password)
  7. keys = require('./RedisKeyBuilder')
  8. logger = require "logger-sharelatex"
  9. module.exports = LockManager =
  10. LOCK_TEST_INTERVAL: 50 # 50ms between each test of the lock
  11. MAX_LOCK_WAIT_TIME: 10000 # 10s maximum time to spend trying to get the lock
  12. tryLock : (doc_id, callback = (err, isFree)->)->
  13. tenSeconds = 10
  14. rclient.set keys.blockingKey(doc_id: doc_id), "locked", "EX", 10, "NX", (err, gotLock)->
  15. return callback(err) if err?
  16. if gotLock == "OK"
  17. metrics.inc "doc-not-blocking"
  18. callback err, true
  19. else
  20. metrics.inc "doc-blocking"
  21. logger.log doc_id: doc_id, redis_response: gotLock, "doc is locked"
  22. callback err, false
  23. getLock: (doc_id, callback = (error) ->) ->
  24. startTime = Date.now()
  25. do attempt = () ->
  26. if Date.now() - startTime > LockManager.MAX_LOCK_WAIT_TIME
  27. return callback(new Error("Timeout"))
  28. LockManager.tryLock doc_id, (error, gotLock) ->
  29. return callback(error) if error?
  30. if gotLock
  31. callback(null)
  32. else
  33. setTimeout attempt, LockManager.LOCK_TEST_INTERVAL
  34. checkLock: (doc_id, callback = (err, isFree)->)->
  35. multi = rclient.multi()
  36. multi.exists keys.blockingKey(doc_id:doc_id)
  37. multi.exec (err, replys)->
  38. return callback(err) if err?
  39. exists = parseInt replys[0]
  40. if exists == 1
  41. metrics.inc "doc-blocking"
  42. callback err, false
  43. else
  44. metrics.inc "doc-not-blocking"
  45. callback err, true
  46. releaseLock: (doc_id, callback)->
  47. rclient.del keys.blockingKey(doc_id:doc_id), callback