diff --git a/services/docstore/app.js b/services/docstore/app.js index a0d7be31ac..d6c499d157 100644 --- a/services/docstore/app.js +++ b/services/docstore/app.js @@ -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) diff --git a/services/docstore/app/js/DocArchiveManager.js b/services/docstore/app/js/DocArchiveManager.js index 9bf9284fd0..a0868d78f6 100644 --- a/services/docstore/app/js/DocArchiveManager.js +++ b/services/docstore/app/js/DocArchiveManager.js @@ -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 }, diff --git a/services/docstore/app/js/HttpController.js b/services/docstore/app/js/HttpController.js index 50c779736c..320557a5f6 100644 --- a/services/docstore/app/js/HttpController.js +++ b/services/docstore/app/js/HttpController.js @@ -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) {} diff --git a/services/docstore/test/acceptance/js/ArchiveDocsTests.js b/services/docstore/test/acceptance/js/ArchiveDocsTests.js index 4a6901f4c7..234ded5a72 100644 --- a/services/docstore/test/acceptance/js/ArchiveDocsTests.js +++ b/services/docstore/test/acceptance/js/ArchiveDocsTests.js @@ -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() diff --git a/services/docstore/test/acceptance/js/helpers/DocstoreClient.js b/services/docstore/test/acceptance/js/helpers/DocstoreClient.js index 237ef42134..92b2b95e21 100644 --- a/services/docstore/test/acceptance/js/helpers/DocstoreClient.js +++ b/services/docstore/test/acceptance/js/helpers/DocstoreClient.js @@ -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) {}