LockManager.js 1.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849
  1. const settings = require('@overleaf/settings')
  2. const RedisWrapper = require('./RedisWrapper')
  3. const rclient = RedisWrapper.client('lock')
  4. const { callbackify, promisify } = require('util')
  5. const RedisWebLocker = require('@overleaf/redis-wrapper/RedisWebLocker')
  6. // this method creates a lock manager with the provided timeout options
  7. function createLockManager(options) {
  8. return new RedisWebLocker({
  9. rclient,
  10. getKey(namespace, id) {
  11. return `lock:web:${namespace}:${id}`
  12. },
  13. options,
  14. })
  15. }
  16. // this is the default lock manager for web
  17. const LockManager = createLockManager(settings.lockManager)
  18. // this method creates a lock manager with a configurable timeout
  19. // it shares the lock keys with the default lock manager
  20. LockManager.withTimeout = function (timeout) {
  21. const overrides = {
  22. redisLockExpiry: timeout, // in seconds
  23. slowExecutionThreshold: 0.5 * timeout * 1000, // in ms
  24. }
  25. const lockManagerSettingsWithTimeout = Object.assign(
  26. {},
  27. settings.lockManager,
  28. overrides
  29. )
  30. return createLockManager(lockManagerSettingsWithTimeout)
  31. }
  32. // need to bind the promisified function when it is part of a class
  33. // see https://nodejs.org/dist/latest-v16.x/docs/api/util.html#utilpromisifyoriginal
  34. const promisifiedRunWithLock = promisify(LockManager.runWithLock).bind(
  35. LockManager
  36. )
  37. LockManager.promises = {
  38. runWithLock(namespace, id, runner) {
  39. const cbRunner = callbackify(runner)
  40. return promisifiedRunWithLock(namespace, id, cbRunner)
  41. },
  42. }
  43. module.exports = LockManager