1
0
mirror of https://github.com/laurent22/joplin.git synced 2025-01-26 18:58:21 +02:00

Fixing sync

This commit is contained in:
Laurent Cozic 2017-06-15 23:12:00 +01:00
parent 4f64831f19
commit cbbadf7d65
2 changed files with 72 additions and 23 deletions

View File

@ -23,6 +23,14 @@ let fileDriver = new FileApiDriverLocal();
let fileApi = new FileApi('/home/laurent/Temp/TestImport', fileDriver); let fileApi = new FileApi('/home/laurent/Temp/TestImport', fileDriver);
let synchronizer = new Synchronizer(db, fileApi); let synchronizer = new Synchronizer(db, fileApi);
function sleep(n) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve();
}, n * 1000);
});
}
function clearDatabase() { function clearDatabase() {
let queries = [ let queries = [
'DELETE FROM changes', 'DELETE FROM changes',
@ -34,6 +42,35 @@ function clearDatabase() {
return db.transactionExecBatch(queries); return db.transactionExecBatch(queries);
} }
async function runTest() {
db.setDebugEnabled(!true);
await db.open({ name: '/home/laurent/Temp/test-sync.sqlite3' });
BaseModel.db_ = db;
await clearDatabase();
let folder = await Folder.save({ title: "folder1" });
let note1 = await Note.save({ title: "un", parent_id: folder.id });
await Note.save({ title: "deux", parent_id: folder.id });
folder = await Folder.save({ title: "folder2" });
await Note.save({ title: "trois", parent_id: folder.id });
await synchronizer.start();
note1 = await Note.load(note1.id);
note1.title = 'un update';
await Note.save(note1);
await synchronizer.start();
}
runTest();
function createRemoteItems() { function createRemoteItems() {
let a = fileApi; let a = fileApi;
return Promise.all([a.mkdir('test1'), a.mkdir('test2'), a.mkdir('test3')]).then(() => { return Promise.all([a.mkdir('test1'), a.mkdir('test2'), a.mkdir('test3')]).then(() => {
@ -56,6 +93,7 @@ async function createLocalItems() {
folder = await Folder.save({ title: "folder2" }); folder = await Folder.save({ title: "folder2" });
await Note.save({ title: "trois", parent_id: folder.id }); await Note.save({ title: "trois", parent_id: folder.id });
// let folder = await Folder.save({ title: "folder1" }); // let folder = await Folder.save({ title: "folder1" });
// await Note.save({ title: "un", parent_id: folder.id }); // await Note.save({ title: "un", parent_id: folder.id });
// await Note.save({ title: "deux", parent_id: folder.id }); // await Note.save({ title: "deux", parent_id: folder.id });
@ -73,16 +111,19 @@ async function createLocalItems() {
// await Note.save({ title: "huit", parent_id: folder.id }); // await Note.save({ title: "huit", parent_id: folder.id });
} }
db.setDebugEnabled(!true);
db.open({ name: '/home/laurent/Temp/test-sync.sqlite3' }).then(() => {
BaseModel.db_ = db;
//return clearDatabase(); // db.setDebugEnabled(!true);
return clearDatabase().then(createLocalItems); // db.open({ name: '/home/laurent/Temp/test-sync.sqlite3' }).then(() => {
}).then(() => { // BaseModel.db_ = db;
return synchronizer.start(); // //return clearDatabase();
}).catch((error) => { // return clearDatabase().then(createLocalItems);
console.error(error); // }).then(() => {
}); // return synchronizer.start();
// }).catch((error) => {
// console.error(error);
// });

View File

@ -10,6 +10,7 @@ import { BaseModel } from 'src/base-model.js';
import { promiseChain } from 'src/promise-utils.js'; import { promiseChain } from 'src/promise-utils.js';
import { NoteFolderService } from 'src/services/note-folder-service.js'; import { NoteFolderService } from 'src/services/note-folder-service.js';
import { time } from 'src/time-utils.js'; import { time } from 'src/time-utils.js';
import { sprintf } from 'sprintf-js';
//import { promiseWhile } from 'src/promise-utils.js'; //import { promiseWhile } from 'src/promise-utils.js';
import moment from 'moment'; import moment from 'moment';
@ -83,10 +84,6 @@ class Synchronizer {
}); });
} }
// isNewerThan(date1, date2) {
// return date1 > date2;
// }
itemByPath(items, path) { itemByPath(items, path) {
for (let i = 0; i < items.length; i++) { for (let i = 0; i < items.length; i++) {
if (items[i].path == path) return items[i]; if (items[i].path == path) return items[i];
@ -95,16 +92,14 @@ class Synchronizer {
} }
itemIsSameDate(item, date) { itemIsSameDate(item, date) {
return Math.abs(item.updatedTime - date) <= 1; return item.updatedTime === date;
} }
itemIsNewerThan(item, date) { itemIsStrictlyNewerThan(item, date) {
if (this.itemIsSameDate(item, date)) return false;
return item.updatedTime > date; return item.updatedTime > date;
} }
itemIsOlderThan(item, date) { itemIsStrictlyOlderThan(item, date) {
if (this.itemIsSameDate(item, date)) return false;
return item.updatedTime < date; return item.updatedTime < date;
} }
@ -177,13 +172,19 @@ class Synchronizer {
action.dest = 'remote'; action.dest = 'remote';
} }
} else { } else {
if (this.itemIsOlderThan(local, local.syncTime)) continue; if (this.itemIsStrictlyOlderThan(local, local.syncTime)) continue;
if (this.itemIsOlderThan(remote, local.syncTime)) { if (this.itemIsStrictlyOlderThan(remote, local.syncTime)) {
action.type = 'update'; action.type = 'update';
action.dest = 'remote'; action.dest = 'remote';
} else { } else if (this.itemIsStrictlyNewerThan(remote, local.syncTime)) {
action.type = 'conflict'; action.type = 'conflict';
action.reason = sprintf('Both remote (%s) and local items (%s) were modified after the last sync (%s).',
moment.unix(remote.updatedTime).toISOString(),
moment.unix(local.updatedTime).toISOString(),
moment.unix(local.syncTime).toISOString()
);
if (local.type == 'folder') { if (local.type == 'folder') {
// For folders, currently we don't completely handle conflicts, we just // For folders, currently we don't completely handle conflicts, we just
// we just update the local dir (.folder metadata file) with the remote // we just update the local dir (.folder metadata file) with the remote
@ -199,6 +200,8 @@ class Synchronizer {
{ type: 'update', dest: 'local' }, { type: 'update', dest: 'local' },
]; ];
} }
} else {
continue; // Neither local nor remote item have been changed recently
} }
} }
@ -226,7 +229,7 @@ class Synchronizer {
action.dest = 'local'; action.dest = 'local';
} }
} else { } else {
if (this.itemIsOlderThan(remote, local.syncTime)) continue; // Already have this version if (this.itemIsStrictlyOlderThan(remote, local.syncTime)) continue; // Already have this version
// Note: no conflict is possible here since if the local item has been // Note: no conflict is possible here since if the local item has been
// modified since the last sync, it's been processed in the previous loop. // modified since the last sync, it's been processed in the previous loop.
action.type = 'update'; action.type = 'update';
@ -265,7 +268,10 @@ class Synchronizer {
if (!action) return Promise.resolve(); if (!action) return Promise.resolve();
console.info('Sync action: ' + action.type + ' ' + action.dest);
if (action.type == 'conflict') { if (action.type == 'conflict') {
console.info(action);
} else { } else {
let syncItem = action[action.dest == 'local' ? 'remote' : 'local']; let syncItem = action[action.dest == 'local' ? 'remote' : 'local'];
@ -372,6 +378,8 @@ class Synchronizer {
for (let i = 0; i < items.length; i++) { for (let i = 0; i < items.length; i++) {
await this.processRemoteItem(items[i]); await this.processRemoteItem(items[i]);
} }
return this.processState('idle');
} }
start() { start() {