mirror of https://github.com/laurent22/joplin.git
All: Fixed race condition when a note is being uploaded while it's being modified in the text editor
parent
29f14681a8
commit
78ce10ddf0
|
@ -830,6 +830,8 @@ describe('Synchronizer', function() {
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should sync resources', asyncTest(async () => {
|
it('should sync resources', asyncTest(async () => {
|
||||||
|
while (insideBeforeEach) await time.msleep(100);
|
||||||
|
|
||||||
let folder1 = await Folder.save({ title: "folder1" });
|
let folder1 = await Folder.save({ title: "folder1" });
|
||||||
let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
|
let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
|
||||||
await shim.attachFileToNote(note1, __dirname + '/../tests/support/photo.jpg');
|
await shim.attachFileToNote(note1, __dirname + '/../tests/support/photo.jpg');
|
||||||
|
|
|
@ -167,7 +167,7 @@ class NoteTextComponent extends React.Component {
|
||||||
async componentWillReceiveProps(nextProps) {
|
async componentWillReceiveProps(nextProps) {
|
||||||
if ('noteId' in nextProps && nextProps.noteId !== this.props.noteId) {
|
if ('noteId' in nextProps && nextProps.noteId !== this.props.noteId) {
|
||||||
await this.reloadNote(nextProps);
|
await this.reloadNote(nextProps);
|
||||||
if(this.editor_){
|
if (this.editor_){
|
||||||
const session = this.editor_.editor.getSession();
|
const session = this.editor_.editor.getSession();
|
||||||
const undoManager = session.getUndoManager();
|
const undoManager = session.getUndoManager();
|
||||||
undoManager.reset();
|
undoManager.reset();
|
||||||
|
|
|
@ -83,6 +83,7 @@ class DecryptionWorker {
|
||||||
});
|
});
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
this.logger().warn('DecryptionWorker: error for: ' + item.id + ' (' + ItemClass.tableName() + ')');
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -320,9 +320,23 @@ class Synchronizer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Note: Currently, we set sync_time to update_time, which should work fine given that the resolution is the millisecond.
|
||||||
|
// In theory though, this could happen:
|
||||||
|
//
|
||||||
|
// 1. t0: Editor: Note is modified
|
||||||
|
// 2. t0: Sync: Found that note was modified so start uploading it
|
||||||
|
// 3. t0: Editor: Note is modified again
|
||||||
|
// 4. t1: Sync: Note has finished uploading, set sync_time to t0
|
||||||
|
//
|
||||||
|
// Later any attempt to sync will not detect that note was modified in (3) (within the same millisecond as it was being uploaded)
|
||||||
|
// because sync_time will be t0 too.
|
||||||
|
//
|
||||||
|
// The solution would be to use something like an etag (a simple counter incremented on every change) to make sure each
|
||||||
|
// change is uniquely identified. Leaving it like this for now.
|
||||||
|
|
||||||
if (canSync) {
|
if (canSync) {
|
||||||
await this.api().setTimestamp(path, local.updated_time);
|
await this.api().setTimestamp(path, local.updated_time);
|
||||||
await ItemClass.saveSyncTime(syncTargetId, local, time.unixMs());
|
await ItemClass.saveSyncTime(syncTargetId, local, local.updated_time);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (action == 'itemConflict') {
|
} else if (action == 'itemConflict') {
|
||||||
|
|
Loading…
Reference in New Issue