Explorar el Código

Merge pull request #180 from overleaf/bg-peek-doc

peek at docs without fetching from mongo
Brian Gough hace 5 años
padre
commit
f0c5d973ba

+ 1 - 0
services/document-updater/app.js

@@ -53,6 +53,7 @@ app.param('doc_id', (req, res, next, docId) => {
 })
 
 app.get('/project/:project_id/doc/:doc_id', HttpController.getDoc)
+app.get('/project/:project_id/doc/:doc_id/peek', HttpController.peekDoc)
 // temporarily keep the GET method for backwards compatibility
 app.get('/project/:project_id/doc', HttpController.getProjectDocsAndFlushIfOld)
 // will migrate to the POST method of get_and_flush_if_old instead

+ 18 - 0
services/document-updater/app/js/HttpController.js

@@ -1,6 +1,7 @@
 const DocumentManager = require('./DocumentManager')
 const HistoryManager = require('./HistoryManager')
 const ProjectManager = require('./ProjectManager')
+const RedisManager = require('./RedisManager')
 const Errors = require('./Errors')
 const logger = require('logger-sharelatex')
 const Settings = require('@overleaf/settings')
@@ -11,6 +12,7 @@ const async = require('async')
 
 module.exports = {
   getDoc,
+  peekDoc,
   getProjectDocsAndFlushIfOld,
   clearProjectState,
   setDoc,
@@ -65,6 +67,22 @@ function getDoc(req, res, next) {
   )
 }
 
+// return the doc from redis if present, but don't load it from mongo
+function peekDoc(req, res, next) {
+  const docId = req.params.doc_id
+  const projectId = req.params.project_id
+  logger.log({ projectId, docId }, 'peeking at doc via http')
+  RedisManager.getDoc(projectId, docId, function (error, lines, version) {
+    if (error) {
+      return next(error)
+    }
+    if (lines == null || version == null) {
+      return next(new Errors.NotFoundError('document not found'))
+    }
+    res.json({ id: docId, lines, version })
+  })
+}
+
 function _getTotalSizeOfLines(lines) {
   let size = 0
   for (const line of lines) {

+ 99 - 0
services/document-updater/test/acceptance/js/PeekingADoc.js

@@ -0,0 +1,99 @@
+const sinon = require('sinon')
+const MockWebApi = require('./helpers/MockWebApi')
+const DocUpdaterClient = require('./helpers/DocUpdaterClient')
+const DocUpdaterApp = require('./helpers/DocUpdaterApp')
+
+describe('Peeking a document', function () {
+  before(function (done) {
+    this.lines = ['one', 'two', 'three']
+    this.version = 42
+    return DocUpdaterApp.ensureRunning(done)
+  })
+
+  describe('when the document is not loaded', function () {
+    before(function (done) {
+      this.project_id = DocUpdaterClient.randomId()
+      this.doc_id = DocUpdaterClient.randomId()
+      sinon.spy(MockWebApi, 'getDocument')
+
+      MockWebApi.insertDoc(this.project_id, this.doc_id, {
+        lines: this.lines,
+        version: this.version,
+      })
+
+      return DocUpdaterClient.peekDoc(
+        this.project_id,
+        this.doc_id,
+        (error, res, returnedDoc) => {
+          this.error = error
+          this.res = res
+          this.returnedDoc = returnedDoc
+          return done()
+        }
+      )
+    })
+
+    after(function () {
+      return MockWebApi.getDocument.restore()
+    })
+
+    it('should return a 404 response', function () {
+      this.res.statusCode.should.equal(404)
+    })
+
+    it('should not load the document from the web API', function () {
+      return MockWebApi.getDocument.called.should.equal(false)
+    })
+  })
+
+  describe('when the document is already loaded', function () {
+    before(function (done) {
+      this.project_id = DocUpdaterClient.randomId()
+      this.doc_id = DocUpdaterClient.randomId()
+
+      MockWebApi.insertDoc(this.project_id, this.doc_id, {
+        lines: this.lines,
+        version: this.version,
+      })
+      return DocUpdaterClient.preloadDoc(
+        this.project_id,
+        this.doc_id,
+        error => {
+          if (error != null) {
+            throw error
+          }
+          sinon.spy(MockWebApi, 'getDocument')
+          return DocUpdaterClient.getDoc(
+            this.project_id,
+            this.doc_id,
+            (error, res, returnedDoc) => {
+              this.res = res
+              this.returnedDoc = returnedDoc
+              return done()
+            }
+          )
+        }
+      )
+    })
+
+    after(function () {
+      return MockWebApi.getDocument.restore()
+    })
+
+    it('should return a 200 response', function () {
+      this.res.statusCode.should.equal(200)
+    })
+
+    it('should return the document lines', function () {
+      return this.returnedDoc.lines.should.deep.equal(this.lines)
+    })
+
+    it('should return the document version', function () {
+      return this.returnedDoc.version.should.equal(this.version)
+    })
+
+    it('should not load the document from the web API', function () {
+      return MockWebApi.getDocument.called.should.equal(false)
+    })
+  })
+})

+ 12 - 0
services/document-updater/test/acceptance/js/helpers/DocUpdaterClient.js

@@ -123,6 +123,18 @@ module.exports = DocUpdaterClient = {
     DocUpdaterClient.getDoc(projectId, docId, callback)
   },
 
+  peekDoc(projectId, docId, callback) {
+    request.get(
+      `http://localhost:3003/project/${projectId}/doc/${docId}/peek`,
+      (error, res, body) => {
+        if (body != null && res.statusCode >= 200 && res.statusCode < 300) {
+          body = JSON.parse(body)
+        }
+        callback(error, res, body)
+      }
+    )
+  },
+
   flushDoc(projectId, docId, callback) {
     request.post(
       `http://localhost:3003/project/${projectId}/doc/${docId}/flush`,

+ 1 - 0
services/document-updater/test/unit/js/HttpController/HttpControllerTests.js

@@ -14,6 +14,7 @@ describe('HttpController', function () {
         './ProjectManager': (this.ProjectManager = {}),
         './ProjectFlusher': { flushAllProjects() {} },
         './DeleteQueueManager': (this.DeleteQueueManager = {}),
+        './RedisManager': (this.RedisManager = {}),
         './Metrics': (this.Metrics = {}),
         './Errors': Errors,
       },