--- /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;