mirror of
https://github.com/overleaf/overleaf.git
synced 2024-10-24 21:12:38 -04:00
5d472e9b38
GitOrigin-RevId: 17909a4dd0717ea4a75288f734ddef19c7d6592e
130 lines
3.7 KiB
JavaScript
130 lines
3.7 KiB
JavaScript
const { expect } = require('chai')
|
|
const sinon = require('sinon')
|
|
const SandboxedModule = require('sandboxed-module')
|
|
const modulePath = require('path').join(
|
|
__dirname,
|
|
'../../../app/js/LockManager'
|
|
)
|
|
const Errors = require('../../../app/js/Errors')
|
|
|
|
describe('LockManager', function () {
|
|
beforeEach(function () {
|
|
this.key = '/local/compile/directory'
|
|
this.clock = sinon.useFakeTimers()
|
|
this.LockManager = SandboxedModule.require(modulePath, {
|
|
requires: {
|
|
'@overleaf/metrics': (this.Metrics = {
|
|
inc: sinon.stub(),
|
|
gauge: sinon.stub(),
|
|
}),
|
|
'@overleaf/settings': (this.Settings = {
|
|
compileConcurrencyLimit: 5,
|
|
}),
|
|
'./Errors': (this.Erros = Errors),
|
|
},
|
|
})
|
|
})
|
|
|
|
afterEach(function () {
|
|
this.clock.restore()
|
|
})
|
|
|
|
describe('when the lock is available', function () {
|
|
it('the lock can be acquired', function () {
|
|
const lock = this.LockManager.acquire(this.key)
|
|
expect(lock).to.exist
|
|
lock.release()
|
|
})
|
|
})
|
|
|
|
describe('after the lock is acquired', function () {
|
|
beforeEach(function () {
|
|
this.lock = this.LockManager.acquire(this.key)
|
|
})
|
|
|
|
afterEach(function () {
|
|
if (this.lock != null) {
|
|
this.lock.release()
|
|
}
|
|
})
|
|
|
|
it("the lock can't be acquired again", function () {
|
|
expect(() => this.LockManager.acquire(this.key)).to.throw(
|
|
Errors.AlreadyCompilingError
|
|
)
|
|
})
|
|
|
|
it('another lock can be acquired', function () {
|
|
const lock = this.LockManager.acquire('another key')
|
|
expect(lock).to.exist
|
|
lock.release()
|
|
})
|
|
|
|
it('the lock can be acquired again after an expiry period', function () {
|
|
// The expiry time is a little bit over 10 minutes. Let's wait 15 minutes.
|
|
this.clock.tick(15 * 60 * 1000)
|
|
this.lock = this.LockManager.acquire(this.key)
|
|
expect(this.lock).to.exist
|
|
})
|
|
|
|
it('the lock can be acquired again after it was released', function () {
|
|
this.lock.release()
|
|
this.lock = this.LockManager.acquire(this.key)
|
|
expect(this.lock).to.exist
|
|
})
|
|
})
|
|
|
|
describe('concurrency limit', function () {
|
|
it('dry run', function () {
|
|
for (let i = 0; i <= this.Settings.compileConcurrencyLimit; i++) {
|
|
this.LockManager.acquire('test_key' + i)
|
|
}
|
|
this.Metrics.inc
|
|
.calledWith('exceeded-compilier-concurrency-limit')
|
|
.should.equal(false)
|
|
this.LockManager.acquire(
|
|
'test_key_' + (this.Settings.compileConcurrencyLimit + 1)
|
|
)
|
|
this.Metrics.inc
|
|
.calledWith('exceeded-compilier-concurrency-limit')
|
|
.should.equal(true)
|
|
})
|
|
|
|
it('exceeding the limit', function () {
|
|
for (let i = 0; i <= this.Settings.compileConcurrencyLimit; i++) {
|
|
this.LockManager.acquire('test_key' + i, false)
|
|
}
|
|
this.Metrics.inc
|
|
.calledWith('exceeded-compilier-concurrency-limit')
|
|
.should.equal(false)
|
|
expect(() =>
|
|
this.LockManager.acquire(
|
|
'test_key_' + (this.Settings.compileConcurrencyLimit + 1),
|
|
false
|
|
)
|
|
).to.throw(Errors.TooManyCompileRequestsError)
|
|
|
|
this.Metrics.inc
|
|
.calledWith('exceeded-compilier-concurrency-limit')
|
|
.should.equal(true)
|
|
})
|
|
|
|
it('within the limit', function () {
|
|
for (let i = 0; i <= this.Settings.compileConcurrencyLimit - 1; i++) {
|
|
this.LockManager.acquire('test_key' + i, false)
|
|
}
|
|
this.Metrics.inc
|
|
.calledWith('exceeded-compilier-concurrency-limit')
|
|
.should.equal(false)
|
|
|
|
const lock = this.LockManager.acquire(
|
|
'test_key_' + this.Settings.compileConcurrencyLimit,
|
|
false
|
|
)
|
|
|
|
expect(lock.key).to.equal(
|
|
'test_key_' + this.Settings.compileConcurrencyLimit
|
|
)
|
|
})
|
|
})
|
|
})
|