overleaf/services/clsi/app/js/LockManager.js
Liangjun Song e2d87f4821 Revert "Revert "log clsi concurrency (#19651)" (#19655)" (#19656)
This reverts commit 3719f468a6336ff4bf5126f3e5d79dcde172b7ea.

GitOrigin-RevId: 6f4809f3c607c62892fc1e110eeaa2a1e7a124a4
2024-07-31 08:04:28 +00:00

51 lines
1.3 KiB
JavaScript

const logger = require('@overleaf/logger')
const Errors = require('./Errors')
const RequestParser = require('./RequestParser')
const Metrics = require('@overleaf/metrics')
// The lock timeout should be higher than the maximum end-to-end compile time.
// Here, we use the maximum compile timeout plus 2 minutes.
const LOCK_TIMEOUT_MS = RequestParser.MAX_TIMEOUT * 1000 + 120000
const LOCKS = new Map()
function acquire(key) {
const currentLock = LOCKS.get(key)
if (currentLock != null) {
if (currentLock.isExpired()) {
logger.warn({ key }, 'Compile lock expired')
currentLock.release()
} else {
throw new Errors.AlreadyCompilingError('compile in progress')
}
}
Metrics.gauge('concurrent_compile_requests', LOCKS.size)
const lock = new Lock(key)
LOCKS.set(key, lock)
return lock
}
class Lock {
constructor(key) {
this.key = key
this.expiresAt = Date.now() + LOCK_TIMEOUT_MS
}
isExpired() {
return Date.now() >= this.expiresAt
}
release() {
const lockWasActive = LOCKS.delete(this.key)
if (!lockWasActive) {
logger.error({ key: this.key }, 'Lock was released twice')
}
if (this.isExpired()) {
Metrics.inc('compile_lock_expired_before_release')
}
}
}
module.exports = { acquire }