Skip to content

Commit

Permalink
fix(reconnect): keep baseVersionEtag during reconnect
Browse files Browse the repository at this point in the history
`this.$syncService` is cleared during the `close` method.

However we need the `baseVersionEtag` to ensure the editing session
on the server
is still in sync with our local ydoc.

Signed-off-by: Max <[email protected]>
  • Loading branch information
max-nextcloud committed Jun 24, 2024
1 parent 6a73132 commit df1131e
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 16 deletions.
37 changes: 23 additions & 14 deletions cypress/e2e/sync.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,22 +47,11 @@ describe('Sync', () => {
})

it('recovers from a short lost connection', () => {
let reconnect = false
cy.intercept('**/apps/text/session/*/*', (req) => {
if (reconnect) {
req.continue()
req.alias = 'alive'
} else {
req.destroy()
req.alias = 'dead'
}
}).as('sessionRequests')
cy.intercept('**/apps/text/session/*/*', req => req.destroy()).as('dead')
cy.wait('@dead', { timeout: 30000 })
cy.get('#editor-container .document-status', { timeout: 30000 })
.should('contain', 'Document could not be loaded.')
.then(() => {
reconnect = true
})
cy.intercept('**/apps/text/session/*/*', req => req.continue()).as('alive')
cy.wait('@alive', { timeout: 30000 })
cy.intercept({ method: 'POST', url: '**/apps/text/session/*/sync' })
.as('syncAfterRecovery')
Expand All @@ -80,6 +69,26 @@ describe('Sync', () => {
.should('include', 'after the lost connection')
})

it('reconnects via button after a short lost connection', () => {
cy.intercept('**/apps/text/session/*/*', req => req.destroy()).as('dead')
cy.wait('@dead', { timeout: 30000 })
cy.get('#editor-container .document-status', { timeout: 30000 })
.should('contain', 'Document could not be loaded.')
cy.get('#editor-container .document-status')
.find('.button.primary').click()
cy.intercept('**/apps/text/session/*/*', req => {
if (req.url.endsWith('create')) {
req.alias = 'create'
}
req.continue()
}).as('alive')
cy.wait('@alive', { timeout: 30000 })
cy.wait('@create', { timeout: 10000 })
.its('request.body')
.should('have.property', 'baseVersionEtag')
.should('not.be.empty')
})

it('recovers from a lost and closed connection', () => {
let reconnect = false
cy.intercept('**/apps/text/session/*/*', (req) => {
Expand Down Expand Up @@ -111,7 +120,7 @@ describe('Sync', () => {
.should('include', 'after the lost connection')
})

it('shows warning when document session got cleaned up', () => {
it('asks to reload page when document session got cleaned up', () => {
cy.get('.save-status button')
.click()
cy.wait('@save')
Expand Down
5 changes: 3 additions & 2 deletions src/components/Editor.vue
Original file line number Diff line number Diff line change
Expand Up @@ -373,7 +373,7 @@ export default {
guestName,
shareToken: this.shareToken,
filePath: this.relativePath,
baseVersionEtag: this.$syncService?.baseVersionEtag,
baseVersionEtag: this.$baseVersionEtag,
forceRecreate: this.forceRecreate,
serialize: this.isRichEditor
? (content) => createMarkdownSerializer(this.$editor.schema).serialize(content ?? this.$editor.state.doc)
Expand Down Expand Up @@ -487,7 +487,7 @@ export default {
})
},

onLoaded({ documentSource, documentState }) {
onLoaded({ document, documentSource, documentState }) {
if (documentState) {
applyDocumentState(this.$ydoc, documentState, this.$providers[0])
// distribute additional state that may exist locally
Expand All @@ -500,6 +500,7 @@ export default {
this.setInitialYjsState(documentSource, { isRichEditor: this.isRichEditor })
}

this.$baseVersionEtag = document.baseVersionEtag
this.hasConnectionIssue = false
const language = extensionHighlight[this.fileExtension] || this.fileExtension;

Expand Down

0 comments on commit df1131e

Please sign in to comment.