소스 검색

[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.
Jakob Ackermann 5 년 전
부모
커밋
9298f486ad

+ 1 - 0
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)
 

+ 21 - 0
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 },

+ 11 - 0
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) {}

+ 68 - 0
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()

+ 12 - 0
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) {}