Просмотр исходного кода

[document-updater] add safe rollback point for history-ot (#25283)

GitOrigin-RevId: d7230dd14a379a27d2c6ab03a006463a18979d06
Jakob Ackermann 1 год назад
Родитель
Сommit
a5e2708eae

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

@@ -212,6 +212,8 @@ app.use((error, req, res, next) => {
     return res.status(422).json(error.info)
     return res.status(422).json(error.info)
   } else if (error instanceof Errors.FileTooLargeError) {
   } else if (error instanceof Errors.FileTooLargeError) {
     return res.sendStatus(413)
     return res.sendStatus(413)
+  } else if (error instanceof Errors.ProjectMigratedToHistoryOTError) {
+    return res.status(422).send(error.message)
   } else if (error.statusCode === 413) {
   } else if (error.statusCode === 413) {
     return res.status(413).send('request entity too large')
     return res.status(413).send('request entity too large')
   } else {
   } else {

+ 2 - 0
services/document-updater/app/js/Errors.js

@@ -5,6 +5,7 @@ class OpRangeNotAvailableError extends OError {}
 class ProjectStateChangedError extends OError {}
 class ProjectStateChangedError extends OError {}
 class DeleteMismatchError extends OError {}
 class DeleteMismatchError extends OError {}
 class FileTooLargeError extends OError {}
 class FileTooLargeError extends OError {}
+class ProjectMigratedToHistoryOTError extends OError {}
 
 
 module.exports = {
 module.exports = {
   NotFoundError,
   NotFoundError,
@@ -12,4 +13,5 @@ module.exports = {
   ProjectStateChangedError,
   ProjectStateChangedError,
   DeleteMismatchError,
   DeleteMismatchError,
   FileTooLargeError,
   FileTooLargeError,
+  ProjectMigratedToHistoryOTError,
 }
 }

+ 7 - 0
services/document-updater/app/js/RedisManager.js

@@ -324,6 +324,13 @@ const RedisManager = {
             } catch (e) {
             } catch (e) {
               return callback(e)
               return callback(e)
             }
             }
+            if (docLines != null && !Array.isArray(docLines)) {
+              return callback(
+                new Errors.ProjectMigratedToHistoryOTError(
+                  'refusing to process doc that was migrated to history-ot'
+                )
+              )
+            }
 
 
             version = parseInt(version || 0, 10)
             version = parseInt(version || 0, 10)
             // check doc is in requested project
             // check doc is in requested project

+ 58 - 0
services/document-updater/test/acceptance/js/GettingADocumentTests.js

@@ -13,6 +13,11 @@ const { expect } = require('chai')
 const MockWebApi = require('./helpers/MockWebApi')
 const MockWebApi = require('./helpers/MockWebApi')
 const DocUpdaterClient = require('./helpers/DocUpdaterClient')
 const DocUpdaterClient = require('./helpers/DocUpdaterClient')
 const DocUpdaterApp = require('./helpers/DocUpdaterApp')
 const DocUpdaterApp = require('./helpers/DocUpdaterApp')
+const Settings = require('@overleaf/settings')
+const docUpdaterRedis = require('@overleaf/redis-wrapper').createClient(
+  Settings.redis.documentupdater
+)
+const Keys = Settings.redis.documentupdater.key_schema
 
 
 describe('Getting a document', function () {
 describe('Getting a document', function () {
   before(function (done) {
   before(function (done) {
@@ -109,6 +114,59 @@ describe('Getting a document', function () {
     })
     })
   })
   })
 
 
+  describe('when the document is migrated (history-ot)', function () {
+    before(function (done) {
+      ;[this.project_id, this.doc_id] = Array.from([
+        DocUpdaterClient.randomId(),
+        DocUpdaterClient.randomId(),
+      ])
+
+      MockWebApi.insertDoc(this.project_id, this.doc_id, {
+        lines: this.lines,
+        version: this.version,
+      })
+      DocUpdaterClient.preloadDoc(this.project_id, this.doc_id, error => {
+        if (error != null) {
+          throw error
+        }
+        sinon.spy(MockWebApi, 'getDocument')
+        docUpdaterRedis.set(
+          Keys.docLines({ doc_id: this.doc_id }),
+          JSON.stringify({ content: this.lines.join('\n') }),
+          err => {
+            if (err) return done(err)
+
+            DocUpdaterClient.getDoc(
+              this.project_id,
+              this.doc_id,
+              (error, res, body) => {
+                if (error) return done(error)
+                this.res = res
+                this.body = body
+                done()
+              }
+            )
+          }
+        )
+      })
+    })
+
+    after(function () {
+      MockWebApi.getDocument.restore()
+    })
+
+    it('should not load the document from the web API', function () {
+      MockWebApi.getDocument.called.should.equal(false)
+    })
+
+    it('should return an error', function () {
+      expect(this.res.statusCode).to.equal(422)
+      expect(this.body).to.equal(
+        'refusing to process doc that was migrated to history-ot'
+      )
+    })
+  })
+
   describe('when the request asks for some recent ops', function () {
   describe('when the request asks for some recent ops', function () {
     before(function (done) {
     before(function (done) {
       ;[this.project_id, this.doc_id] = Array.from([
       ;[this.project_id, this.doc_id] = Array.from([