All: Fixed race condition when a note is being uploaded while it's being modified in the text editor

pull/112/head^2
Laurent Cozic 2018-01-08 20:09:01 +01:00
parent 29f14681a8
commit 78ce10ddf0
4 changed files with 19 additions and 2 deletions

View File

@ -830,6 +830,8 @@ describe('Synchronizer', function() {
}));
it('should sync resources', asyncTest(async () => {
while (insideBeforeEach) await time.msleep(100);
let folder1 = await Folder.save({ title: "folder1" });
let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
await shim.attachFileToNote(note1, __dirname + '/../tests/support/photo.jpg');

View File

@ -167,7 +167,7 @@ class NoteTextComponent extends React.Component {
async componentWillReceiveProps(nextProps) {
if ('noteId' in nextProps && nextProps.noteId !== this.props.noteId) {
await this.reloadNote(nextProps);
if(this.editor_){
if (this.editor_){
const session = this.editor_.editor.getSession();
const undoManager = session.getUndoManager();
undoManager.reset();

View File

@ -83,6 +83,7 @@ class DecryptionWorker {
});
continue;
}
this.logger().warn('DecryptionWorker: error for: ' + item.id + ' (' + ItemClass.tableName() + ')');
throw error;
}
}

View File

@ -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) {
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') {