Explorar o código

Merge pull request #3169 from overleaf/bg-fix-doc-race

prevent unflushed doc from being removed from openDocs

GitOrigin-RevId: 79733fdc589d1981faf577174431d65f9dbe30e7
Brian Gough %!s(int64=6) %!d(string=hai) anos
pai
achega
d54400af61

+ 21 - 1
services/web/frontend/js/ide/editor/Document.js

@@ -31,6 +31,17 @@ export default (Document = (function() {
       if (!this.openDocs) {
       if (!this.openDocs) {
         this.openDocs = {}
         this.openDocs = {}
       }
       }
+      // Try to clean up existing docs before reopening them. If the doc has no
+      // buffered ops then it will be deleted by _cleanup() and a new instance
+      // of the document created below. This prevents us trying to follow the
+      // joinDoc:existing code path on an existing doc that doesn't have any
+      // local changes and getting an error if its version is too old.
+      if (this.openDocs[doc_id]) {
+        sl_console.log(
+          `[getDocument] Cleaning up existing document instance for ${doc_id}`
+        )
+        this.openDocs[doc_id]._cleanUp()
+      }
       if (this.openDocs[doc_id] == null) {
       if (this.openDocs[doc_id] == null) {
         sl_console.log(
         sl_console.log(
           `[getDocument] Creating new document instance for ${doc_id}`
           `[getDocument] Creating new document instance for ${doc_id}`
@@ -247,6 +258,7 @@ export default (Document = (function() {
       if (callback == null) {
       if (callback == null) {
         callback = function(error) {}
         callback = function(error) {}
       }
       }
+      this.flush() // force an immediate flush when leaving document
       this.wantToBeJoined = false
       this.wantToBeJoined = false
       this._cancelJoin()
       this._cancelJoin()
       if (this.doc != null && this.doc.hasBufferedOps()) {
       if (this.doc != null && this.doc.hasBufferedOps()) {
@@ -560,7 +572,15 @@ export default (Document = (function() {
     }
     }
 
 
     _cleanUp() {
     _cleanUp() {
-      if (Document.openDocs[this.doc_id] === this) {
+      // if we arrive here from _onError the pending and inflight ops will have been cleared
+      if (this.hasBufferedOps()) {
+        sl_console.log(
+          `[_cleanUp] Document (${
+            this.doc_id
+          }) has buffered ops, refusing to remove from openDocs`
+        )
+        return // return immediately, do not unbind from events
+      } else if (Document.openDocs[this.doc_id] === this) {
         sl_console.log(
         sl_console.log(
           `[_cleanUp] Removing self (${this.doc_id}) from in openDocs`
           `[_cleanUp] Removing self (${this.doc_id}) from in openDocs`
         )
         )

+ 4 - 0
services/web/frontend/js/ide/editor/EditorManager.js

@@ -226,6 +226,10 @@ export default (EditorManager = (function() {
       const editorOpenDocEpoch = ++this.editorOpenDocEpoch
       const editorOpenDocEpoch = ++this.editorOpenDocEpoch
       return new_sharejs_doc.join(error => {
       return new_sharejs_doc.join(error => {
         if (error != null) {
         if (error != null) {
+          sl_console.log(
+            `[_openNewDocument] error joining doc ${doc.id}`,
+            error
+          )
           return callback(error)
           return callback(error)
         }
         }
         if (this.editorOpenDocEpoch !== editorOpenDocEpoch) {
         if (this.editorOpenDocEpoch !== editorOpenDocEpoch) {