Merge pull request #9647 from overleaf/bg-dropbox-to-overleaf-existing-doc

handle updates to existing doc in dropbox to overleaf metadata

GitOrigin-RevId: e82955a4a76e62fb649263a94103fdb7f322de85
This commit is contained in:
Eric Mc Sween 2022-09-21 08:01:32 -04:00 committed by Copybot
parent 76e0265ed7
commit 59cdcccc26
9 changed files with 77 additions and 51 deletions

View file

@ -238,14 +238,22 @@ module.exports = DocumentManager = {
// Otherwise we should remove it immediately since nothing else // Otherwise we should remove it immediately since nothing else
// is using it. // is using it.
if (alreadyLoaded) { if (alreadyLoaded) {
DocumentManager.flushDocIfLoaded(projectId, docId, error => { DocumentManager.flushDocIfLoaded(
projectId,
docId,
(error, result) => {
if (error) { if (error) {
return callback(error) return callback(error)
} }
callback(null) callback(null, result)
}) }
)
} else { } else {
DocumentManager.flushAndDeleteDoc(projectId, docId, {}, error => { DocumentManager.flushAndDeleteDoc(
projectId,
docId,
{},
(error, result) => {
// There is no harm in flushing project history if the previous // There is no harm in flushing project history if the previous
// call failed and sometimes it is required // call failed and sometimes it is required
HistoryManager.flushProjectChangesAsync(projectId) HistoryManager.flushProjectChangesAsync(projectId)
@ -253,8 +261,9 @@ module.exports = DocumentManager = {
if (error) { if (error) {
return callback(error) return callback(error)
} }
callback(null) callback(null, result)
}) }
)
} }
}) })
}) })
@ -302,11 +311,16 @@ module.exports = DocumentManager = {
ranges, ranges,
lastUpdatedAt, lastUpdatedAt,
lastUpdatedBy, lastUpdatedBy,
error => { (error, result) => {
if (error) { if (error) {
return callback(error) return callback(error)
} }
RedisManager.clearUnflushedTime(docId, callback) RedisManager.clearUnflushedTime(docId, err => {
if (err) {
return callback(err)
}
callback(null, result)
})
} }
) )
} }
@ -321,7 +335,7 @@ module.exports = DocumentManager = {
_callback(...args) _callback(...args)
} }
DocumentManager.flushDocIfLoaded(projectId, docId, error => { DocumentManager.flushDocIfLoaded(projectId, docId, (error, result) => {
if (error) { if (error) {
if (options.ignoreFlushErrors) { if (options.ignoreFlushErrors) {
logger.warn( logger.warn(
@ -340,7 +354,7 @@ module.exports = DocumentManager = {
if (error) { if (error) {
return callback(error) return callback(error)
} }
callback(null) callback(null, result)
}) })
}) })
}, },

View file

@ -163,13 +163,13 @@ function setDoc(req, res, next) {
source, source,
userId, userId,
undoing, undoing,
error => { (error, result) => {
timer.done() timer.done()
if (error) { if (error) {
return next(error) return next(error)
} }
logger.debug({ projectId, docId }, 'set doc via http') logger.debug({ projectId, docId }, 'set doc via http')
res.sendStatus(204) // No Content res.json(result)
} }
) )
} }

View file

@ -159,7 +159,7 @@ function setDoc(
return callback(new Error('error connecting to web API')) return callback(new Error('error connecting to web API'))
} }
if (res.statusCode >= 200 && res.statusCode < 300) { if (res.statusCode >= 200 && res.statusCode < 300) {
callback(null) callback(null, body)
} else if (res.statusCode === 404) { } else if (res.statusCode === 404) {
callback(new Errors.NotFoundError(`doc not not found: ${urlPath}`)) callback(new Errors.NotFoundError(`doc not not found: ${urlPath}`))
} else if (res.statusCode === 413) { } else if (res.statusCode === 413) {

View file

@ -76,6 +76,7 @@ describe('Setting a document', function () {
return done(error) return done(error)
} }
this.statusCode = res.statusCode this.statusCode = res.statusCode
this.body = body
done() done()
} }
) )
@ -91,8 +92,8 @@ describe('Setting a document', function () {
MockWebApi.setDocument.resetHistory() MockWebApi.setDocument.resetHistory()
}) })
it('should return a 204 status code', function () { it('should return a 200 status code', function () {
this.statusCode.should.equal(204) this.statusCode.should.equal(200)
}) })
it('should send the updated doc lines and version to the web api', function () { it('should send the updated doc lines and version to the web api', function () {
@ -141,6 +142,10 @@ describe('Setting a document', function () {
} }
) )
}) })
it('should return the mongo rev in the json response', function () {
this.body.should.deep.equal({ rev: '123' })
})
}) })
describe('when the updated doc does not exist in the doc updater', function () { describe('when the updated doc does not exist in the doc updater', function () {
@ -163,6 +168,7 @@ describe('Setting a document', function () {
return done(error) return done(error)
} }
this.statusCode = res.statusCode this.statusCode = res.statusCode
this.body = body
setTimeout(done, 200) setTimeout(done, 200)
} }
) )
@ -174,8 +180,8 @@ describe('Setting a document', function () {
MockWebApi.setDocument.resetHistory() MockWebApi.setDocument.resetHistory()
}) })
it('should return a 204 status code', function () { it('should return a 200 status code', function () {
this.statusCode.should.equal(204) this.statusCode.should.equal(200)
}) })
it('should send the updated doc lines to the web api', function () { it('should send the updated doc lines to the web api', function () {
@ -206,6 +212,10 @@ describe('Setting a document', function () {
} }
) )
}) })
it('should return the mongo rev in the json response', function () {
this.body.should.deep.equal({ rev: '123' })
})
}) })
const DOC_TOO_LARGE_TEST_CASES = [ const DOC_TOO_LARGE_TEST_CASES = [
@ -302,6 +312,7 @@ describe('Setting a document', function () {
return done(error) return done(error)
} }
this.statusCode = res.statusCode this.statusCode = res.statusCode
this.body = body
setTimeout(done, 200) setTimeout(done, 200)
} }
) )
@ -313,8 +324,8 @@ describe('Setting a document', function () {
MockWebApi.setDocument.resetHistory() MockWebApi.setDocument.resetHistory()
}) })
it('should return a 204 status code', function () { it('should return a 200 status code', function () {
this.statusCode.should.equal(204) this.statusCode.should.equal(200)
}) })
it('should send the updated doc lines to the web api', function () { it('should send the updated doc lines to the web api', function () {
@ -322,6 +333,10 @@ describe('Setting a document', function () {
.calledWith(this.project_id, this.doc_id, this.newLines) .calledWith(this.project_id, this.doc_id, this.newLines)
.should.equal(true) .should.equal(true)
}) })
it('should return the mongo rev in the json response', function () {
this.body.should.deep.equal({ rev: '123' })
})
}) })
describe('with track changes', function () { describe('with track changes', function () {

View file

@ -99,7 +99,7 @@ module.exports = MockWebApi = {
if (error != null) { if (error != null) {
return res.sendStatus(500) return res.sendStatus(500)
} else { } else {
return res.sendStatus(204) return res.json({ rev: '123' })
} }
} }
) )

View file

@ -17,6 +17,7 @@ describe('HttpController', function () {
'./RedisManager': (this.RedisManager = {}), './RedisManager': (this.RedisManager = {}),
'./Metrics': (this.Metrics = {}), './Metrics': (this.Metrics = {}),
'./Errors': Errors, './Errors': Errors,
'@overleaf/settings': { max_doc_length: 2 * 1024 * 1024 },
}, },
}) })
this.Metrics.Timer = class Timer {} this.Metrics.Timer = class Timer {}
@ -202,7 +203,9 @@ describe('HttpController', function () {
describe('successfully', function () { describe('successfully', function () {
beforeEach(function () { beforeEach(function () {
this.DocumentManager.setDocWithLock = sinon.stub().callsArgWith(6) this.DocumentManager.setDocWithLock = sinon
.stub()
.callsArgWith(6, null, { rev: '123' })
this.HttpController.setDoc(this.req, this.res, this.next) this.HttpController.setDoc(this.req, this.res, this.next)
}) })
@ -219,8 +222,8 @@ describe('HttpController', function () {
.should.equal(true) .should.equal(true)
}) })
it('should return a successful No Content response', function () { it('should return a json response with the document rev from web', function () {
this.res.sendStatus.calledWith(204).should.equal(true) this.res.json.calledWithMatch({ rev: '123' }).should.equal(true)
}) })
it('should log the request', function () { it('should log the request', function () {

View file

@ -94,7 +94,7 @@ function setDocument(req, res, next) {
ranges, ranges,
lastUpdatedAt, lastUpdatedAt,
lastUpdatedBy, lastUpdatedBy,
error => { (error, result) => {
if (error) { if (error) {
OError.tag(error, 'error finding element for getDocument', { OError.tag(error, 'error finding element for getDocument', {
docId, docId,
@ -106,7 +106,7 @@ function setDocument(req, res, next) {
{ docId, projectId }, { docId, projectId },
'finished receiving set document request from api (docupdater)' 'finished receiving set document request from api (docupdater)'
) )
res.sendStatus(200) res.json(result)
} }
) )
} }

View file

@ -201,7 +201,7 @@ const ProjectEntityUpdateHandler = {
) )
// path will only be present if the doc is not deleted // path will only be present if the doc is not deleted
if (!modified || isDeletedDoc) { if (!modified || isDeletedDoc) {
return callback() return callback(null, { rev })
} }
// Don't need to block for marking as updated // Don't need to block for marking as updated
ProjectUpdateHandler.markAsUpdated( ProjectUpdateHandler.markAsUpdated(
@ -218,7 +218,12 @@ const ProjectEntityUpdateHandler = {
rev, rev,
folderId: folder?._id, folderId: folder?._id,
}, },
callback err => {
if (err) {
return callback(err)
}
callback(null, { rev, modified })
}
) )
} }
) )
@ -741,7 +746,7 @@ const ProjectEntityUpdateHandler = {
userId, userId,
docLines, docLines,
source, source,
err => { (err, result) => {
if (err != null) { if (err != null) {
return callback(err) return callback(err)
} }
@ -749,16 +754,11 @@ const ProjectEntityUpdateHandler = {
{ projectId, docId: existingDoc._id }, { projectId, docId: existingDoc._id },
'notifying users that the document has been updated' 'notifying users that the document has been updated'
) )
DocumentUpdaterHandler.flushDocToMongo( // there is no need to flush the doc to mongo at this point as docupdater
projectId, // flushes it as part of setDoc.
existingDoc._id, //
err => { // combine rev from response with existing doc metadata
if (err != null) { callback(null, { ...existingDoc, ...result }, existingDoc == null)
return callback(err)
}
callback(null, existingDoc, existingDoc == null)
}
)
} }
) )
} else { } else {

View file

@ -790,12 +790,6 @@ describe('ProjectEntityUpdateHandler', function () {
.should.equal(true) .should.equal(true)
}) })
it('flushes the doc contents', function () {
this.DocumentUpdaterHandler.flushDocToMongo
.calledWith(projectId, this.existingDoc._id)
.should.equal(true)
})
it('returns the doc', function () { it('returns the doc', function () {
this.callback.calledWith(null, this.existingDoc, false) this.callback.calledWith(null, this.existingDoc, false)
}) })