Skip to content

Commit 28ee3e7

Browse files
committed
fix(SaveService): Don't autosave if yjs reports pendingStructs
Yjs pendingStructs most likely mean that the local yjs document state is missing a step. So let's not autosave such an inconstent state to the server. Signed-off-by: Jonas <[email protected]>
1 parent 07cc286 commit 28ee3e7

File tree

4 files changed

+31
-1
lines changed

4 files changed

+31
-1
lines changed

src/components/Editor.vue

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -801,6 +801,10 @@ export default defineComponent({
801801
this.translateModal = false
802802
},
803803
804+
hasYjsPendingStructs() {
805+
return !!this.ydoc.store.pendingStructs
806+
},
807+
804808
saveBeforeUnload() {
805809
this.saveService.saveViaSendBeacon()
806810
},

src/components/Editor/Status.vue

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@
1111
:class="saveStatusClass">
1212
<NcButton
1313
type="tertiary"
14-
:aria-label="t('text', 'Save document')"
14+
:disabled="saveService.hasYjsPendingStructs()"
15+
:title="saveTitle"
16+
:aria-label="saveAriaLabel"
1517
@click="onClickSave">
1618
<template #icon>
1719
<NcSavingIndicatorIcon
@@ -122,6 +124,16 @@ export default {
122124
}
123125
return this.dirtyStateIndicator ? 'saving' : 'saved'
124126
},
127+
saveTitle() {
128+
return this.saveService.hasYjsPendingStructs()
129+
? ('text', 'Cannot save due to inconsistent sync state')
130+
: ''
131+
},
132+
saveAriaLabel() {
133+
return this.saveService.hasYjsPendingStructs()
134+
? ('text', 'Cannot save due to inconsistent sync state')
135+
: ('text', 'Save document')
136+
},
125137
lastSavedString() {
126138
// Make this a dependent of refreshMoment, so it will be recomputed
127139
/* eslint-disable-next-line no-unused-expressions */

src/composables/useSaveService.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ export const provideSaveService = (
2323
syncService,
2424
serialize,
2525
getDocumentState: () => getDocumentState(ydoc),
26+
hasYjsPendingStructs: () => !!ydoc.store.pendingStructs,
2627
})
2728
provide(saveServiceKey, saveService)
2829
return { saveService }

src/services/SaveService.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,23 +23,27 @@ class SaveService {
2323
syncService
2424
serialize
2525
getDocumentState
26+
hasYjsPendingStructs
2627
autosave
2728

2829
constructor({
2930
connection,
3031
syncService,
3132
serialize,
3233
getDocumentState,
34+
hasYjsPendingStructs,
3335
}: {
3436
connection: ShallowRef<Connection | undefined>
3537
syncService: SyncService
3638
serialize: () => string
3739
getDocumentState: () => string
40+
hasYjsPendingStructs: () => boolean
3841
}) {
3942
this.connection = connection
4043
this.syncService = syncService
4144
this.serialize = serialize
4245
this.getDocumentState = getDocumentState
46+
this.hasYjsPendingStructs = hasYjsPendingStructs
4347
this.autosave = debounce(this._autosave.bind(this), AUTOSAVE_INTERVAL)
4448
this.syncService.on('close', () => {
4549
this.autosave.clear()
@@ -64,6 +68,11 @@ class SaveService {
6468
logger.warn('Could not save due to missing connection')
6569
return
6670
}
71+
// Don't save if we have pendingStructs (i.e. document state misses a step)
72+
if (this.hasYjsPendingStructs()) {
73+
logger.debug('[SaveService] not saving due to inconsistent yjs state')
74+
return
75+
}
6776
try {
6877
const response = await save(this.connection.value, {
6978
version: this.version,
@@ -86,6 +95,10 @@ class SaveService {
8695
if (!this.connection.value) {
8796
return
8897
}
98+
// Don't save if we have pendingStructs (i.e. document state misses a step)
99+
if (this.hasYjsPendingStructs()) {
100+
return
101+
}
89102
saveViaSendBeacon(this.connection.value, {
90103
version: this.version,
91104
autosaveContent: this._getContent(),

0 commit comments

Comments
 (0)