mirror of
https://github.com/overleaf/overleaf.git
synced 2025-01-15 00:51:12 +00:00
4d70bd664f
These changes were previously merged, not deployed, and reverted. This reverts the revert. This reverts commit a6b8c6c658b33b6eee78b8b99e43308f32211ae2, reversing changes made to 93c98921372eed4244d22fce800716cb27eca299.
199 lines
6.2 KiB
JavaScript
199 lines
6.2 KiB
JavaScript
/* eslint-disable
|
|
handle-callback-err,
|
|
no-return-assign,
|
|
no-unused-vars,
|
|
*/
|
|
// TODO: This file was created by bulk-decaffeinate.
|
|
// Fix any style issues and re-enable lint.
|
|
/*
|
|
* decaffeinate suggestions:
|
|
* DS102: Remove unnecessary code created because of implicit returns
|
|
* DS207: Consider shorter variations of null checks
|
|
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
|
*/
|
|
const sinon = require('sinon')
|
|
const modulePath = '../../../../app/js/DispatchManager.js'
|
|
const SandboxedModule = require('sandboxed-module')
|
|
const Errors = require('../../../../app/js/Errors.js')
|
|
|
|
describe('DispatchManager', function () {
|
|
beforeEach(function () {
|
|
let Timer
|
|
this.timeout(3000)
|
|
this.DispatchManager = SandboxedModule.require(modulePath, {
|
|
requires: {
|
|
'./UpdateManager': (this.UpdateManager = {}),
|
|
'settings-sharelatex': (this.settings = {
|
|
redis: {
|
|
documentupdater: {}
|
|
}
|
|
}),
|
|
'@overleaf/redis-wrapper': (this.redis = {}),
|
|
'./RateLimitManager': {},
|
|
'./Errors': Errors,
|
|
'./Metrics': (this.Metrics = {
|
|
Timer: (Timer = (function () {
|
|
Timer = class Timer {
|
|
static initClass() {
|
|
this.prototype.done = sinon.stub()
|
|
}
|
|
}
|
|
Timer.initClass()
|
|
return Timer
|
|
})())
|
|
})
|
|
}
|
|
})
|
|
this.callback = sinon.stub()
|
|
return (this.RateLimiter = {
|
|
run(task, cb) {
|
|
return task(cb)
|
|
}
|
|
})
|
|
}) // run task without rate limit
|
|
|
|
return describe('each worker', function () {
|
|
beforeEach(function () {
|
|
this.client = { auth: sinon.stub() }
|
|
this.redis.createClient = sinon.stub().returns(this.client)
|
|
return (this.worker = this.DispatchManager.createDispatcher(
|
|
this.RateLimiter,
|
|
0
|
|
))
|
|
})
|
|
|
|
it('should create a new redis client', function () {
|
|
return this.redis.createClient.called.should.equal(true)
|
|
})
|
|
|
|
describe('_waitForUpdateThenDispatchWorker', function () {
|
|
beforeEach(function () {
|
|
this.project_id = 'project-id-123'
|
|
this.doc_id = 'doc-id-123'
|
|
this.doc_key = `${this.project_id}:${this.doc_id}`
|
|
return (this.client.blpop = sinon
|
|
.stub()
|
|
.callsArgWith(2, null, ['pending-updates-list', this.doc_key]))
|
|
})
|
|
|
|
describe('in the normal case', function () {
|
|
beforeEach(function () {
|
|
this.UpdateManager.processOutstandingUpdatesWithLock = sinon
|
|
.stub()
|
|
.callsArg(2)
|
|
return this.worker._waitForUpdateThenDispatchWorker(this.callback)
|
|
})
|
|
|
|
it('should call redis with BLPOP', function () {
|
|
return this.client.blpop
|
|
.calledWith('pending-updates-list', 0)
|
|
.should.equal(true)
|
|
})
|
|
|
|
it('should call processOutstandingUpdatesWithLock', function () {
|
|
return this.UpdateManager.processOutstandingUpdatesWithLock
|
|
.calledWith(this.project_id, this.doc_id)
|
|
.should.equal(true)
|
|
})
|
|
|
|
it('should not log any errors', function () {
|
|
this.logger.error.called.should.equal(false)
|
|
return this.logger.warn.called.should.equal(false)
|
|
})
|
|
|
|
return it('should call the callback', function () {
|
|
return this.callback.called.should.equal(true)
|
|
})
|
|
})
|
|
|
|
describe('with an error', function () {
|
|
beforeEach(function () {
|
|
this.UpdateManager.processOutstandingUpdatesWithLock = sinon
|
|
.stub()
|
|
.callsArgWith(2, new Error('a generic error'))
|
|
return this.worker._waitForUpdateThenDispatchWorker(this.callback)
|
|
})
|
|
|
|
it('should log an error', function () {
|
|
return this.logger.error.called.should.equal(true)
|
|
})
|
|
|
|
return it('should call the callback', function () {
|
|
return this.callback.called.should.equal(true)
|
|
})
|
|
})
|
|
|
|
describe("with a 'Delete component' error", function () {
|
|
beforeEach(function () {
|
|
this.UpdateManager.processOutstandingUpdatesWithLock = sinon
|
|
.stub()
|
|
.callsArgWith(2, new Errors.DeleteMismatchError())
|
|
return this.worker._waitForUpdateThenDispatchWorker(this.callback)
|
|
})
|
|
|
|
it('should log a warning', function () {
|
|
return this.logger.warn.called.should.equal(true)
|
|
})
|
|
|
|
return it('should call the callback', function () {
|
|
return this.callback.called.should.equal(true)
|
|
})
|
|
})
|
|
|
|
describe('pending updates list with shard key', function () {
|
|
beforeEach(function (done) {
|
|
this.client = {
|
|
auth: sinon.stub(),
|
|
blpop: sinon.stub().callsArgWith(2)
|
|
}
|
|
this.redis.createClient = sinon.stub().returns(this.client)
|
|
this.queueShardNumber = 7
|
|
this.worker = this.DispatchManager.createDispatcher(
|
|
this.RateLimiter,
|
|
this.queueShardNumber
|
|
)
|
|
this.worker._waitForUpdateThenDispatchWorker(done)
|
|
})
|
|
|
|
it('should call redis with BLPOP with the correct key', function () {
|
|
this.client.blpop
|
|
.calledWith(`pending-updates-list-${this.queueShardNumber}`, 0)
|
|
.should.equal(true)
|
|
})
|
|
})
|
|
})
|
|
|
|
return describe('run', function () {
|
|
return it('should call _waitForUpdateThenDispatchWorker until shutting down', function (done) {
|
|
let callCount = 0
|
|
this.worker._waitForUpdateThenDispatchWorker = (callback) => {
|
|
if (callback == null) {
|
|
callback = function (error) {}
|
|
}
|
|
callCount++
|
|
if (callCount === 3) {
|
|
this.settings.shuttingDown = true
|
|
}
|
|
return setTimeout(() => callback(), 10)
|
|
}
|
|
sinon.spy(this.worker, '_waitForUpdateThenDispatchWorker')
|
|
|
|
this.worker.run()
|
|
|
|
var checkStatus = () => {
|
|
if (!this.settings.shuttingDown) {
|
|
// retry until shutdown
|
|
setTimeout(checkStatus, 100)
|
|
} else {
|
|
this.worker._waitForUpdateThenDispatchWorker.callCount.should.equal(
|
|
3
|
|
)
|
|
return done()
|
|
}
|
|
}
|
|
|
|
return checkStatus()
|
|
})
|
|
})
|
|
})
|
|
})
|