Files
desktop-app/node_modules/sync.js
2015-01-24 00:46:25 +08:00

339 lines
8.0 KiB
JavaScript

var db = require('db');
var Common = require('common');
var User = require('user');
var Tags = db.tags;
var needle = require('needle');
var fs = require('fs');
var Api = require('api');
var Notebook = require('notebook');
var Note = require('note');
function log(o) {
console.log(o);
}
// 同步服务
var Sync = {
// 同步的信息, 返回给调用者
_syncInfo: {
notebook: {adds: [], deletes: [], updates: []},
note: {adds: [], deletes: [], updates: [], conflicts: []},
tag: {}
},
// notebook
_syncNotebookIsLastChunk: false,
_totalSyncNotebookNum: 0, // 需要同步的数量
_tocalHasSyncNotebookNum: 0, // 已同步的数量
_notebookMaxEntry: 1,
// note
_syncNoteIsLastChunk: false,
_totalSyncNoteNum: 0, // 需要同步的数量
_noteMaxEntry: 1,
_initSyncInfo: function() {
var me = this;
// notebook
me._syncNotebookIsLastChunk = false;
me._totalSyncNotebookNum = 0;
me._totalHasSyncNotebookNum = 0;
me._lockNotebook = 1;
// note
me._syncNoteIsLastChunk = false;
me._totalSyncNoteNum = 0;
me._totalHasSyncNoteNum = 0;
me._lockNote = 1;
me._syncInfo = {
notebook: {ok: false, adds: [], deletes: [], updates: []},
note: {ok: false, adds: [], deletes: [], updates: [], conflicts: []},
tag: {ok: false}
};
},
//---------------
// notebook
//---------------
// 增加, 有锁
_lockNotebook: 1,
_addSyncNotebookNum: function() {
var me = this;
if(me._lockNotebook) {
me._lockNotebook = 0;
me._totalHasSyncNotebookNum++;
me._lockNotebook = 1;
} else {
me._addSyncNotebookNum();
}
},
// 同步笔记本
_syncNotebookToLocal: function(notebooks, callback) {
var me = this;
function canCall() {
// 是最后一块, 且
me._addSyncNotebookNum();
log(me._totalHasSyncNotebookNum + ' ' + me._totalSyncNotebookNum);
if(me._syncNotebookIsLastChunk && me._totalHasSyncNotebookNum >= me._totalSyncNotebookNum) {
me._syncInfo.notebook.ok = true;
callback && callback(true);
}
}
if(!notebooks || notebooks.length == 0) {
return canCall();
}
for(var i in notebooks) {
var notebook = notebooks[i];
// 得到本地的, 与之对比
(function(notebook) {
var usn = notebook.Usn;
var notebookId = notebook.NotebookId;
// 1) 服务器端删除了, 本地肯定删除
if(notebook.IsDeleted) {
log('delete: ');
log(notebook);
Notebook.deleteNotebookForce(notebookId, function() {
me._syncInfo.notebook.deletes.push(notebookId);
canCall();
});
return;
}
// 2) 查看本地的, 与本地合并
Notebook.getNotebook(notebookId, function(notebookLocal) {
// 2.1 本地没有, 表示是新建
if(!notebookLocal) {
log('add: ...')
// TODO
Notebook.addNotebookForce(notebook, function(notebook) {
me._syncInfo.notebook.adds.push(notebook);
canCall();
});
} else {
// 2.2 本地是否修改了, 需要合并, 使用服务端的数据
if(notebook.IsDirty) {
log('冲突....')
// 2.3 服务器是最新的, 用服务器的
} else {
}
// 这里都是用服务器端的数据, 不处理冲突
Notebook.updateNotebookForce(notebook, function(notebook) {
if(notebook) {
me._syncInfo.notebook.updates.push(notebook);
}
canCall();
})
}
});
})(notebook);
}
},
syncNotebook: function(afterUsn, callback) {
var me = this;
Api.getSyncNotebooks(afterUsn, me._notebookMaxEntry, function(notebooks) {
log('syncNotebook')
log(notebooks);
if(Common.isOk(notebooks)) {
me._totalSyncNotebookNum += notebooks.length;
// 证明可能还有要同步的
if(notebooks.length == me._notebookMaxEntry) {
me._syncNotebookToLocal(notebooks);
var last = notebooks[notebooks.length-1];
me.syncNotebook(last.Usn, callback);
} else {
log('no more');
me._syncNotebookIsLastChunk = true;
me._syncNotebookToLocal(notebooks, callback);
}
} else {
// 同步失败
me._syncInfo.notebook.ok = false;
me._syncInfo.notebook.msg = "cann't get all chunks";
callback && callback(false);
}
});
},
//-------------
// note
//-------------
// 增加, 有锁
_lockNote: 1,
_addSyncNoteNum: function() {
var me = this;
if(me._lockNote) {
me._lockNote = 0;
me._totalHasSyncNoteNum++;
me._lockNote = 1;
} else {
me._addSyncNoteNum();
}
},
// 同步笔记到本地
_syncNoteToLocal: function(notes, callback) {
var me = this;
function canCall() {
// 是最后一块, 且
me._addSyncNoteNum();
log('notes: ' + me._totalHasSyncNoteNum + ' ' + me._totalSyncNoteNum + ' ' + me._syncNoteIsLastChunk);
if(me._syncNoteIsLastChunk && me._totalHasSyncNoteNum >= me._totalSyncNoteNum) {
me._syncInfo.note.ok = true;
callback && callback(true);
}
}
if(!notes || notes.length == 0) {
return canCall();
}
for(var i in notes) {
var note = notes[i];
// 得到本地的, 与之对比
(function(note) {
var usn = note.Usn;
var noteId = note.NoteId;
// 1) 服务器端删除了, 本地肯定删除
if(note.IsDeleted) {
log('delete: ');
log(note);
Note.deleteNoteForce(noteId, function() {
me._syncInfo.note.deletes.push(noteId);
canCall();
});
return;
}
// 2) 查看本地的, 与本地合并
Note.getNote(noteId, function(noteLocal) {
// 2.1 本地没有, 表示是新建
if(!noteLocal) {
log('add: ...')
Note.addNoteForce(note, function(note) {
me._syncInfo.note.adds.push(note);
return canCall();
});
} else {
// 2.2 本地是否修改了, 冲突, 报告给前端, 前端处理
// 冲突, 将本地修改的笔记复制一份(设置冲突字段, ConflictNoteId), 远程的覆盖本地的
if(note.IsDirty) {
log('冲突....')
me._syncInfo.note.conflicts.push(note);
return canCall();
// 2.3 服务器是最新的, 用服务器的
} else {
// 服务器是最新的, 本地没动过, 则覆盖之
Note.updateNoteForce(note, function(note) {
if(note) {
me._syncInfo.note.updates.push(note);
}
canCall();
});
}
}
});
})(note);
}
},
syncNote: function(afterUsn, callback) {
var me = this;
Api.getSyncNotes(afterUsn, me._noteMaxEntry, function(notes) {
log('syncNote')
log(notes);
if(Common.isOk(notes)) {
me._totalSyncNoteNum += notes.length;
// 证明可能还有要同步的
if(notes.length == me._noteMaxEntry) {
me._syncNoteToLocal(notes);
var last = notes[notes.length-1];
me.syncNote(last.Usn, callback);
} else {
log('no more');
me._syncNoteIsLastChunk = true;
me._syncNoteToLocal(notes, callback);
}
} else {
// 同步失败
me._syncInfo.note.ok = false;
me._syncInfo.note.msg = "cann't get all chunks";
callback && callback(false);
}
});
},
// 同步标签
syncTag: function(afterUsn, callback) {
callback && callback(true);
},
// 全量同步
fullSync: function(callback) {
var me = this;
me._initSyncInfo();
// 同步笔记本
me.syncNotebook(-1, function(ok) {
if(ok) {
log('------------------')
// 同步笔记
me.syncNote(-1, function(ok) {
if(ok) {
// 同步标签
me.syncTag(-1, function() {
callback && callback(me._syncInfo);
});
} else {
callback && callback(me._syncInfo);
}
});
} else {
log('no-------')
callback && callback(me._syncInfo);
}
});
},
// 增量同步
incrSync: function() {
var me = this;
me._initSyncInfo();
log('full sync start');
// 得到当前LastSyncUsn
User.getLastSyncInfo(function(lastSyncUsn, lastSyncTime) {
// 同步笔记本
me.syncNotebook(-1, function() {
// 同步笔记
me.syncNote(-1, function() {
// 同步标签
me.syncTag(-1, function() {
callback && callback(me._syncInfo);
});
});
});
});
},
// 发送改变
sendChanges: function() {
}
};
module.exports = Sync;