mirror of
https://github.com/laurent22/joplin.git
synced 2025-01-26 18:58:21 +02:00
Fixing sync
This commit is contained in:
parent
4f64831f19
commit
cbbadf7d65
@ -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);
|
||||||
|
// });
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -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() {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user