client/src/sagas/BaseSyncronizer.js
changeset 168 ea92f4fe783d
parent 129 d48946d164c6
equal deleted inserted replaced
167:1f340f3597a8 168:ea92f4fe783d
     1 import { put } from 'redux-saga/effects'
     1 import { put } from 'redux-saga/effects';
     2 import Immutable from 'immutable';
     2 import * as R from 'ramda';
       
     3 import { ActionEnum } from '../constants';
       
     4 
       
     5 const testLocalListHas = R.useWith(R.compose,[R.contains, R.prop]);
       
     6 const getPropValues = R.compose(R.values, R.prop);
     3 
     7 
     4 export const SyncMixin = Base => class extends Base {
     8 export const SyncMixin = Base => class extends Base {
     5 
     9 
     6   constructor(syncEntries, client) {
    10   constructor(syncEntries, client) {
     7     super();
    11     super();
     8     this.syncEntries = syncEntries;
    12     this.syncEntries = syncEntries;
     9     this.client = client;
    13     this.client = client;
    10     this.localDiffs = null;
    14     this.localDiffs = null;
    11   }
    15   }
    12 
    16 
    13   // abstract methods
       
    14 
       
    15   // local diffs (immutable)
       
    16   // getLocalDiffs()
       
    17 
       
    18   // remote urls
       
    19   // getRemoteLoadUrl()
       
    20   // getRemoteDeleteUrl(localObjInst);
       
    21   // getRemoteCreateUrl(localObjInst)
       
    22   // getRemoteUpdateUrl(localObjInst)
       
    23 
       
    24   // build remote json message
       
    25   // getRemoteData(localObjInst)
       
    26   // getLocalRecord(remoteObj)
       
    27 
       
    28   // actions
       
    29   // doDeleteLocalObj(localObjId);
       
    30   // resetLocalObj(localObjInst)
       
    31   // loadObj(objRecord)
       
    32 
       
    33 
    17 
    34   * loadFromRemote() {
    18   * loadFromRemote() {
    35 
    19     const objIds = R.compose(R.map(R.prop('ext_id')),R.reject(R.propEq('action', ActionEnum.UPDATED)))(this.syncEntries);
    36     const objIds = this.syncEntries
       
    37       .filter((syncEntry) => syncEntry.action !== 2)
       
    38       .map((syncEntry) => syncEntry.ext_id);
       
    39 
    20 
    40     if(objIds.length === 0) {
    21     if(objIds.length === 0) {
    41       return ;
    22       return ;
    42     }
    23     }
    43 
    24 
    44     //TODO: manage pagination
    25     //TODO: manage pagination
    45     const remoteObjs = yield this.client.get(this.getRemoteLoadUrl(), { ext_id__in: objIds.join(',') })
    26     const remoteObjs = yield this.client.get(this.getRemoteLoadUrl(), { ext_id__in: objIds.join(',') })
    46 
    27 
    47     for (var remoteObj of remoteObjs.results) {
    28     for (var remoteObj of remoteObjs.results) {
    48 
    29 
    49       if(this.localDiffs.get('deleted').has(remoteObj.ext_id)) {
    30       if(testLocalListHas(remoteObj.ext_id, 'deleted')(this.localDiffs)) {
       
    31       // if(this.localDiffs.get('deleted').has(remoteObj.ext_id)) {
    50         // The session has been deleted locally, we will delete it later
    32         // The session has been deleted locally, we will delete it later
    51         continue;
    33         continue;
    52       }
    34       }
    53 
    35 
    54       if(this.localDiffs.get('created').has(remoteObj.ext_id)) {
    36       if(testLocalListHas(remoteObj.ext_id, 'created')(this.localDiffs)) {
       
    37       // if(this.localDiffs.get('created').has(remoteObj.ext_id)) {
    55         // The session has been modified both locally and remotely
    38         // The session has been modified both locally and remotely
    56         // the server wins, it will be loaded locally, we must remove it from the list of locally changed sessions
    39         // the server wins, it will be loaded locally, we must remove it from the list of locally changed sessions
    57         const newCreatedMap = this.localDiffs.get('created').delete(remoteObj.ext_id);
    40         this.localDiffs = R.merge(this.localDiffs, { created: R.omit([remoteObj.ext_id,], this.localDiffs.created) } );
    58         this.localDiffs = this.localDiffs.set('created', newCreatedMap);
    41         // const newCreatedMap = this.localDiffs.get('created').delete(remoteObj.ext_id);
       
    42         // this.localDiffs = this.localDiffs.set('created', newCreatedMap);
    59       }
    43       }
    60 
    44 
    61       if(this.localDiffs.get('updated').has(remoteObj.ext_id)) {
    45       if(testLocalListHas(remoteObj.ext_id, 'updated')(this.localDiffs)) {
    62         // The session has been modified both locally and remotely
    46         // The session has been modified both locally and remotely
    63         // the server wins, it will be loaded locally, we must remove it from the list of locally changed sessions
    47         // the server wins, it will be loaded locally, we must remove it from the list of locally changed sessions
    64         const newModifiedMap = this.localDiffs.get('updated').delete(remoteObj.ext_id);
    48         // const newModifiedMap = this.localDiffs.get('updated').delete(remoteObj.ext_id);
    65         this.localDiffs = this.localDiffs.set('updated', newModifiedMap);
    49         // this.localDiffs = this.localDiffs.set('updated', newModifiedMap);
       
    50         this.localDiffs = R.merge(this.localDiffs, { updated: R.omit([remoteObj.ext_id,], this.localDiffs.updated) } );
    66       }
    51       }
    67 
    52 
    68       let objRecord = this.getLocalRecord(remoteObj);
    53       let objRecord = this.getLocalRecord(remoteObj);
    69       yield put(this.loadObj(objRecord));
    54       yield put(this.loadObj(objRecord));
    70     }
    55     }
    74 
    59 
    75     const objToDelete = this.syncEntries
    60     const objToDelete = this.syncEntries
    76       .filter((syncObj) => syncObj.action === 2)
    61       .filter((syncObj) => syncObj.action === 2)
    77       .map((syncObj) => syncObj.ext_id);
    62       .map((syncObj) => syncObj.ext_id);
    78 
    63 
    79     let deleteObjs = this.localDiffs.get('deleted');
    64     let deleteObjs = R.prop('deleted', this.localDiffs);
    80     let updatedObjs = this.localDiffs.get('updated');
    65     let updatedObjs = R.prop('updated', this.localDiffs);
    81     let createdObjs = this.localDiffs.get('created');
    66     let createdObjs = R.prop('created', this.localDiffs);
    82     for (var objId of objToDelete) {
    67     for (var objId of objToDelete) {
    83       if(deleteObjs.has(objId)) {
    68       const omitObjId = R.omit([objId,])
    84         // we remove it from the list of sessions to delete
    69       deleteObjs = omitObjId(deleteObjs);
    85         deleteObjs = deleteObjs.delete(objId);
    70       updatedObjs = omitObjId(updatedObjs);
    86       }
    71       createdObjs = omitObjId(createdObjs);
    87       if(updatedObjs.has(objId)) {
       
    88         updatedObjs = updatedObjs.delete(objId);
       
    89       }
       
    90       if(createdObjs.has(objId)) {
       
    91         createdObjs = createdObjs.delete(objId);
       
    92       }
       
    93       yield put(this.doDeleteLocalObj(objId));
    72       yield put(this.doDeleteLocalObj(objId));
    94     }
    73     }
    95     this.localDiffs = Immutable.Map({created: createdObjs, updated: updatedObjs, deleted: deleteObjs});
    74     this.localDiffs = {created: createdObjs, updated: updatedObjs, deleted: deleteObjs};
    96   }
    75   }
    97 
    76 
    98   * syncObjects() {
    77   * syncObjects() {
    99 
    78 
   100     this.localDiffs = yield this.getLocalDiffs();
    79     this.localDiffs = yield this.getLocalDiffs();
   101 
    80 
   102     yield this.loadFromRemote();
    81     yield this.loadFromRemote();
   103     yield this.deleteFromRemote();
    82     yield this.deleteFromRemote();
   104 
    83 
   105     let localObjInst;
    84     let localObjInst;
       
    85     const getLocalDiffPropValues = R.flip(getPropValues)(this.localDiffs);
   106 
    86 
   107     // delete remote obj
    87     // delete remote obj
   108     for(localObjInst of this.localDiffs.get('deleted').values()) {
    88     for(localObjInst of getLocalDiffPropValues('deleted')) {
   109 
    89 
   110       try {
    90       try {
   111         yield this.client.delete(this.getRemoteDeleteUrl(localObjInst));
    91         yield this.client.delete(this.getRemoteDeleteUrl(localObjInst));
   112       } catch(err) {
    92       } catch(err) {
   113         if(err.status !== 404) {
    93         if(err.status !== 404) {
   115           console.log("error whe deleting object", err);
    95           console.log("error whe deleting object", err);
   116         }
    96         }
   117         // otherwise, this is ok
    97         // otherwise, this is ok
   118       }
    98       }
   119 
    99 
   120       yield put(this.doDeleteLocalObj(localObjInst.get('_id')));
   100       yield put(this.doDeleteLocalObj(localObjInst._id));
   121     }
   101     }
   122 
   102 
   123     for(localObjInst of this.localDiffs.get('created').values()) {
   103     for(localObjInst of getLocalDiffPropValues('created')) {
   124       const remoteData = this.getRemoteData(localObjInst);
   104       const remoteData = this.getRemoteData(localObjInst);
   125       //TODO: SET VERSION !!!!
   105       //TODO: SET VERSION !!!!
   126       yield this.client.post(this.getRemoteCreateUrl(localObjInst), remoteData);
   106       yield this.client.post(this.getRemoteCreateUrl(localObjInst), remoteData);
   127       yield put(this.resetLocalObj(localObjInst));
   107       yield put(this.resetLocalObj(localObjInst));
   128     }
   108     }
   129 
   109 
   130     for(localObjInst of this.localDiffs.get('updated').values()) {
   110     for(localObjInst of getLocalDiffPropValues('updated')) {
   131       const remoteData = this.getRemoteData(localObjInst);
   111       const remoteData = this.getRemoteData(localObjInst);
   132       //TODO: SET VERSION !!!!
   112       //TODO: SET VERSION !!!!
   133       yield this.client.put(this.getRemoteUpdateUrl(localObjInst), remoteData);
   113       yield this.client.put(this.getRemoteUpdateUrl(localObjInst), remoteData);
   134       yield put(this.resetLocalObj(localObjInst));
   114       yield put(this.resetLocalObj(localObjInst));
   135     }
   115     }