[app] add a new route for archiving a single doc

There is a minor opportunity for optimizing the mongo call(s) for
 archiving: we should include `{ inS3: false }` in the queries instead
 of filtering locally. It's been like that for years now, so it can
 stay a little longer.
This commit is contained in:
Jakob Ackermann 2021-01-04 11:55:47 +00:00
parent bbcc47a2c4
commit 9298f486ad
5 changed files with 113 additions and 0 deletions

View file

@ -56,6 +56,7 @@ app.post(
app.delete('/project/:project_id/doc/:doc_id', HttpController.deleteDoc)
app.post('/project/:project_id/archive', HttpController.archiveAllDocs)
app.post('/project/:project_id/doc/:doc_id/archive', HttpController.archiveDoc)
app.post('/project/:project_id/unarchive', HttpController.unArchiveAllDocs)
app.post('/project/:project_id/destroy', HttpController.destroyAllDocs)

View file

@ -13,6 +13,7 @@ const PARALLEL_JOBS = 5
module.exports = {
archiveAllDocs: callbackify(archiveAllDocs),
archiveDocById: callbackify(archiveDocById),
archiveDoc: callbackify(archiveDoc),
unArchiveAllDocs: callbackify(unArchiveAllDocs),
unarchiveDoc: callbackify(unarchiveDoc),
@ -20,6 +21,7 @@ module.exports = {
destroyDoc: callbackify(destroyDoc),
promises: {
archiveAllDocs,
archiveDocById,
archiveDoc,
unArchiveAllDocs,
unarchiveDoc,
@ -45,6 +47,25 @@ async function archiveAllDocs(projectId) {
})
}
async function archiveDocById(projectId, docId) {
const doc = await MongoManager.findDoc(projectId, docId, {
lines: true,
ranges: true,
rev: true,
inS3: true
})
if (!doc) {
throw new Errors.NotFoundError(
`Cannot find doc ${docId} in project ${projectId}`
)
}
// TODO(das7pad): consider refactoring MongoManager.findDoc to take a query
if (doc.inS3) return
return archiveDoc(projectId, doc)
}
async function archiveDoc(projectId, doc) {
logger.log(
{ project_id: projectId, doc_id: doc._id },

View file

@ -222,6 +222,17 @@ module.exports = HttpController = {
})
},
archiveDoc(req, res, next) {
const { project_id, doc_id } = req.params
logger.log({ project_id, doc_id }, 'archiving a doc')
DocArchive.archiveDocById(project_id, doc_id, function (error) {
if (error) {
return next(error)
}
res.sendStatus(204)
})
},
unArchiveAllDocs(req, res, next) {
if (next == null) {
next = function (error) {}

View file

@ -275,6 +275,74 @@ describe('Archiving', function () {
})
})
describe('archiving a single doc', function () {
before(function (done) {
this.project_id = ObjectId()
this.timeout(1000 * 30)
this.doc = {
_id: ObjectId(),
lines: ['foo', 'bar'],
ranges: {},
version: 2
}
DocstoreClient.createDoc(
this.project_id,
this.doc._id,
this.doc.lines,
this.doc.version,
this.doc.ranges,
(error) => {
if (error) {
return done(error)
}
DocstoreClient.archiveDocById(
this.project_id,
this.doc._id,
(error, res) => {
this.res = res
if (error) {
return done(error)
}
done()
}
)
}
)
})
it('should successully archive the doc', function (done) {
this.res.statusCode.should.equal(204)
done()
})
it('should set inS3 and unset lines and ranges in the doc', function (done) {
db.docs.findOne({ _id: this.doc._id }, (error, doc) => {
if (error) {
return done(error)
}
should.not.exist(doc.lines)
should.not.exist(doc.ranges)
doc.inS3.should.equal(true)
done()
})
})
it('should set the doc in s3 correctly', function (done) {
DocstoreClient.getS3Doc(
this.project_id,
this.doc._id,
(error, s3_doc) => {
if (error) {
return done(error)
}
s3_doc.lines.should.deep.equal(this.doc.lines)
s3_doc.ranges.should.deep.equal(this.doc.ranges)
done()
}
)
})
})
describe('a doc with large lines', function () {
before(function (done) {
this.project_id = ObjectId()

View file

@ -129,6 +129,18 @@ module.exports = DocstoreClient = {
)
},
archiveDocById(project_id, doc_id, callback) {
if (callback == null) {
callback = function (error, res, body) {}
}
return request.post(
{
url: `http://localhost:${settings.internal.docstore.port}/project/${project_id}/doc/${doc_id}/archive`
},
callback
)
},
destroyAllDoc(project_id, callback) {
if (callback == null) {
callback = function (error, res, body) {}