mirror of
https://github.com/overleaf/overleaf.git
synced 2025-03-06 08:31:45 +00:00
Merge pull request #5892 from overleaf/tm-large-docs-in-resync
Do size check on doc before queuing resyncDocContent GitOrigin-RevId: 315b849375fd17a2936adacaad4a93ccf283d853
This commit is contained in:
parent
830123df98
commit
4f32ddc4cb
2 changed files with 94 additions and 2 deletions
|
@ -23,6 +23,7 @@ const rclient = require('@overleaf/redis-wrapper').createClient(
|
||||||
)
|
)
|
||||||
const logger = require('@overleaf/logger')
|
const logger = require('@overleaf/logger')
|
||||||
const metrics = require('./Metrics')
|
const metrics = require('./Metrics')
|
||||||
|
const { docIsTooLarge } = require('./Limits')
|
||||||
|
|
||||||
module.exports = ProjectHistoryRedisManager = {
|
module.exports = ProjectHistoryRedisManager = {
|
||||||
queueOps(project_id, ...rest) {
|
queueOps(project_id, ...rest) {
|
||||||
|
@ -162,6 +163,16 @@ module.exports = ProjectHistoryRedisManager = {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
const jsonUpdate = JSON.stringify(projectUpdate)
|
const jsonUpdate = JSON.stringify(projectUpdate)
|
||||||
|
// Do an optimised size check on the docLines using the serialised
|
||||||
|
// project update length as an upper bound
|
||||||
|
const sizeBound = jsonUpdate.length
|
||||||
|
if (docIsTooLarge(sizeBound, lines, Settings.max_doc_length)) {
|
||||||
|
const err = new Error(
|
||||||
|
'blocking resync doc content insert into project history queue: doc is too large'
|
||||||
|
)
|
||||||
|
logger.error({ project_id, doc_id, err, docSize: sizeBound }, err.message)
|
||||||
|
return callback(err)
|
||||||
|
}
|
||||||
return ProjectHistoryRedisManager.queueOps(project_id, jsonUpdate, callback)
|
return ProjectHistoryRedisManager.queueOps(project_id, jsonUpdate, callback)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,11 +24,17 @@ describe('ProjectHistoryRedisManager', function () {
|
||||||
this.callback = sinon.stub()
|
this.callback = sinon.stub()
|
||||||
this.rclient = {}
|
this.rclient = {}
|
||||||
tk.freeze(new Date())
|
tk.freeze(new Date())
|
||||||
|
|
||||||
|
this.Limits = {
|
||||||
|
docIsTooLarge: sinon.stub().returns(false),
|
||||||
|
}
|
||||||
|
|
||||||
return (this.ProjectHistoryRedisManager = SandboxedModule.require(
|
return (this.ProjectHistoryRedisManager = SandboxedModule.require(
|
||||||
modulePath,
|
modulePath,
|
||||||
{
|
{
|
||||||
requires: {
|
requires: {
|
||||||
'@overleaf/settings': (this.settings = {
|
'@overleaf/settings': (this.settings = {
|
||||||
|
max_doc_length: 123,
|
||||||
redis: {
|
redis: {
|
||||||
project_history: {
|
project_history: {
|
||||||
key_schema: {
|
key_schema: {
|
||||||
|
@ -46,6 +52,7 @@ describe('ProjectHistoryRedisManager', function () {
|
||||||
createClient: () => this.rclient,
|
createClient: () => this.rclient,
|
||||||
},
|
},
|
||||||
'./Metrics': (this.metrics = { summary: sinon.stub() }),
|
'./Metrics': (this.metrics = { summary: sinon.stub() }),
|
||||||
|
'./Limits': this.Limits,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
))
|
))
|
||||||
|
@ -186,8 +193,82 @@ describe('ProjectHistoryRedisManager', function () {
|
||||||
return it('should queue an update', function () {})
|
return it('should queue an update', function () {})
|
||||||
})
|
})
|
||||||
|
|
||||||
return describe('queueResyncDocContent', function () {
|
describe('queueResyncDocContent', function () {
|
||||||
return it('should queue an update', function () {})
|
beforeEach(function () {
|
||||||
|
this.doc_id = 1234
|
||||||
|
this.lines = ['one', 'two']
|
||||||
|
this.version = 2
|
||||||
|
this.pathname = '/path'
|
||||||
|
|
||||||
|
this.update = {
|
||||||
|
resyncDocContent: {
|
||||||
|
content: this.lines.join('\n'),
|
||||||
|
version: this.version,
|
||||||
|
},
|
||||||
|
projectHistoryId: this.projectHistoryId,
|
||||||
|
path: this.pathname,
|
||||||
|
doc: this.doc_id,
|
||||||
|
meta: {
|
||||||
|
ts: new Date(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
this.ProjectHistoryRedisManager.queueOps = sinon.stub()
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('with a good doc', function () {
|
||||||
|
beforeEach(function () {
|
||||||
|
this.ProjectHistoryRedisManager.queueResyncDocContent(
|
||||||
|
this.project_id,
|
||||||
|
this.projectHistoryId,
|
||||||
|
this.doc_id,
|
||||||
|
this.lines,
|
||||||
|
this.version,
|
||||||
|
this.pathname,
|
||||||
|
this.callback
|
||||||
|
)
|
||||||
|
})
|
||||||
|
it('should check if the doc is too large', function () {
|
||||||
|
this.Limits.docIsTooLarge
|
||||||
|
.calledWith(
|
||||||
|
JSON.stringify(this.update).length,
|
||||||
|
this.lines,
|
||||||
|
this.settings.max_doc_length
|
||||||
|
)
|
||||||
|
.should.equal(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should queue an update', function () {
|
||||||
|
this.ProjectHistoryRedisManager.queueOps
|
||||||
|
.calledWithExactly(
|
||||||
|
this.project_id,
|
||||||
|
JSON.stringify(this.update),
|
||||||
|
this.callback
|
||||||
|
)
|
||||||
|
.should.equal(true)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('with a doc that is too large', function () {
|
||||||
|
beforeEach(function () {
|
||||||
|
this.Limits.docIsTooLarge.returns(true)
|
||||||
|
this.ProjectHistoryRedisManager.queueResyncDocContent(
|
||||||
|
this.project_id,
|
||||||
|
this.projectHistoryId,
|
||||||
|
this.doc_id,
|
||||||
|
this.lines,
|
||||||
|
this.version,
|
||||||
|
this.pathname,
|
||||||
|
this.callback
|
||||||
|
)
|
||||||
|
})
|
||||||
|
it('should not queue an update if the doc is too large', function () {
|
||||||
|
this.ProjectHistoryRedisManager.queueOps.called.should.equal(false)
|
||||||
|
this.callback
|
||||||
|
.calledWith(sinon.match.instanceOf(Error))
|
||||||
|
.should.equal(true)
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
Loading…
Reference in a new issue