diff -r 34a75bd8d0b9 -r d48946d164c6 client/src/sagas/BaseSyncronizer.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/client/src/sagas/BaseSyncronizer.js Fri Jul 28 19:40:35 2017 +0200 @@ -0,0 +1,140 @@ +import { put } from 'redux-saga/effects' +import Immutable from 'immutable'; + +export const SyncMixin = Base => class extends Base { + + constructor(syncEntries, client) { + super(); + this.syncEntries = syncEntries; + this.client = client; + this.localDiffs = null; + } + + // abstract methods + + // local diffs (immutable) + // getLocalDiffs() + + // remote urls + // getRemoteLoadUrl() + // getRemoteDeleteUrl(localObjInst); + // getRemoteCreateUrl(localObjInst) + // getRemoteUpdateUrl(localObjInst) + + // build remote json message + // getRemoteData(localObjInst) + // getLocalRecord(remoteObj) + + // actions + // doDeleteLocalObj(localObjId); + // resetLocalObj(localObjInst) + // loadObj(objRecord) + + + * loadFromRemote() { + + const objIds = this.syncEntries + .filter((syncEntry) => syncEntry.action !== 2) + .map((syncEntry) => syncEntry.ext_id); + + if(objIds.length === 0) { + return ; + } + + //TODO: manage pagination + const remoteObjs = yield this.client.get(this.getRemoteLoadUrl(), { ext_id__in: objIds.join(',') }) + + for (var remoteObj of remoteObjs.results) { + + if(this.localDiffs.get('deleted').has(remoteObj.ext_id)) { + // The session has been deleted locally, we will delete it later + continue; + } + + if(this.localDiffs.get('created').has(remoteObj.ext_id)) { + // The session has been modified both locally and remotely + // the server wins, it will be loaded locally, we must remove it from the list of locally changed sessions + const newCreatedMap = this.localDiffs.get('created').delete(remoteObj.ext_id); + this.localDiffs = this.localDiffs.set('created', newCreatedMap); + } + + if(this.localDiffs.get('updated').has(remoteObj.ext_id)) { + // The session has been modified both locally and remotely + // the server wins, it will be loaded locally, we must remove it from the list of locally changed sessions + const newModifiedMap = this.localDiffs.get('updated').delete(remoteObj.ext_id); + this.localDiffs = this.localDiffs.set('updated', newModifiedMap); + } + + let objRecord = this.getLocalRecord(remoteObj); + yield put(this.loadObj(objRecord)); + } + } + + * deleteFromRemote() { + + const objToDelete = this.syncEntries + .filter((syncObj) => syncObj.action === 2) + .map((syncObj) => syncObj.ext_id); + + let deleteObjs = this.localDiffs.get('deleted'); + let updatedObjs = this.localDiffs.get('updated'); + let createdObjs = this.localDiffs.get('created'); + for (var objId of objToDelete) { + if(deleteObjs.has(objId)) { + // we remove it from the list of sessions to delete + deleteObjs = deleteObjs.delete(objId); + } + if(updatedObjs.has(objId)) { + updatedObjs = updatedObjs.delete(objId); + } + if(createdObjs.has(objId)) { + createdObjs = createdObjs.delete(objId); + } + yield put(this.doDeleteLocalObj(objId)); + } + this.localDiffs = Immutable.Map({created: createdObjs, updated: updatedObjs, deleted: deleteObjs}); + } + + * syncObjects() { + + this.localDiffs = yield this.getLocalDiffs(); + + yield this.loadFromRemote(); + yield this.deleteFromRemote(); + + let localObjInst; + + // delete remote obj + for(localObjInst of this.localDiffs.get('deleted').values()) { + + try { + yield this.client.delete(this.getRemoteDeleteUrl(localObjInst)); + } catch(err) { + if(err.status !== 404) { + //TODO: better error handling ??? + console.log("error whe deleting object", err); + } + // otherwise, this is ok + } + + yield put(this.doDeleteLocalObj(localObjInst.get('_id'))); + } + + for(localObjInst of this.localDiffs.get('created').values()) { + const remoteData = this.getRemoteData(localObjInst); + //TODO: SET VERSION !!!! + yield this.client.post(this.getRemoteCreateUrl(localObjInst), remoteData); + yield put(this.resetLocalObj(localObjInst)); + } + + for(localObjInst of this.localDiffs.get('updated').values()) { + const remoteData = this.getRemoteData(localObjInst); + //TODO: SET VERSION !!!! + yield this.client.put(this.getRemoteUpdateUrl(localObjInst), remoteData); + yield put(this.resetLocalObj(localObjInst)); + } + + } +} + +export default SyncMixin;