LockManager.js 1.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445
  1. const logger = require('@overleaf/logger')
  2. const Errors = require('./Errors')
  3. const RequestParser = require('./RequestParser')
  4. // The lock timeout should be higher than the maximum end-to-end compile time.
  5. // Here, we use the maximum compile timeout plus 2 minutes.
  6. const LOCK_TIMEOUT_MS = RequestParser.MAX_TIMEOUT * 1000 + 120000
  7. const LOCKS = new Map()
  8. function acquire(key) {
  9. const currentLock = LOCKS.get(key)
  10. if (currentLock != null) {
  11. if (currentLock.isExpired()) {
  12. logger.warn({ key }, 'Compile lock expired')
  13. currentLock.release()
  14. } else {
  15. throw new Errors.AlreadyCompilingError('compile in progress')
  16. }
  17. }
  18. const lock = new Lock(key)
  19. LOCKS.set(key, lock)
  20. return lock
  21. }
  22. class Lock {
  23. constructor(key) {
  24. this.key = key
  25. this.expiresAt = Date.now() + LOCK_TIMEOUT_MS
  26. }
  27. isExpired() {
  28. return Date.now() >= this.expiresAt
  29. }
  30. release() {
  31. const lockWasActive = LOCKS.delete(this.key)
  32. if (!lockWasActive) {
  33. logger.error({ key: this.key }, 'Lock was released twice')
  34. }
  35. }
  36. }
  37. module.exports = { acquire }