client/src/sagas/BaseSyncronizer.js
changeset 129 d48946d164c6
child 168 ea92f4fe783d
equal deleted inserted replaced
128:34a75bd8d0b9 129:d48946d164c6
       
     1 import { put } from 'redux-saga/effects'
       
     2 import Immutable from 'immutable';
       
     3 
       
     4 export const SyncMixin = Base => class extends Base {
       
     5 
       
     6   constructor(syncEntries, client) {
       
     7     super();
       
     8     this.syncEntries = syncEntries;
       
     9     this.client = client;
       
    10     this.localDiffs = null;
       
    11   }
       
    12 
       
    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 
       
    34   * loadFromRemote() {
       
    35 
       
    36     const objIds = this.syncEntries
       
    37       .filter((syncEntry) => syncEntry.action !== 2)
       
    38       .map((syncEntry) => syncEntry.ext_id);
       
    39 
       
    40     if(objIds.length === 0) {
       
    41       return ;
       
    42     }
       
    43 
       
    44     //TODO: manage pagination
       
    45     const remoteObjs = yield this.client.get(this.getRemoteLoadUrl(), { ext_id__in: objIds.join(',') })
       
    46 
       
    47     for (var remoteObj of remoteObjs.results) {
       
    48 
       
    49       if(this.localDiffs.get('deleted').has(remoteObj.ext_id)) {
       
    50         // The session has been deleted locally, we will delete it later
       
    51         continue;
       
    52       }
       
    53 
       
    54       if(this.localDiffs.get('created').has(remoteObj.ext_id)) {
       
    55         // 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
       
    57         const newCreatedMap = this.localDiffs.get('created').delete(remoteObj.ext_id);
       
    58         this.localDiffs = this.localDiffs.set('created', newCreatedMap);
       
    59       }
       
    60 
       
    61       if(this.localDiffs.get('updated').has(remoteObj.ext_id)) {
       
    62         // 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
       
    64         const newModifiedMap = this.localDiffs.get('updated').delete(remoteObj.ext_id);
       
    65         this.localDiffs = this.localDiffs.set('updated', newModifiedMap);
       
    66       }
       
    67 
       
    68       let objRecord = this.getLocalRecord(remoteObj);
       
    69       yield put(this.loadObj(objRecord));
       
    70     }
       
    71   }
       
    72 
       
    73   * deleteFromRemote() {
       
    74 
       
    75     const objToDelete = this.syncEntries
       
    76       .filter((syncObj) => syncObj.action === 2)
       
    77       .map((syncObj) => syncObj.ext_id);
       
    78 
       
    79     let deleteObjs = this.localDiffs.get('deleted');
       
    80     let updatedObjs = this.localDiffs.get('updated');
       
    81     let createdObjs = this.localDiffs.get('created');
       
    82     for (var objId of objToDelete) {
       
    83       if(deleteObjs.has(objId)) {
       
    84         // we remove it from the list of sessions to delete
       
    85         deleteObjs = deleteObjs.delete(objId);
       
    86       }
       
    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));
       
    94     }
       
    95     this.localDiffs = Immutable.Map({created: createdObjs, updated: updatedObjs, deleted: deleteObjs});
       
    96   }
       
    97 
       
    98   * syncObjects() {
       
    99 
       
   100     this.localDiffs = yield this.getLocalDiffs();
       
   101 
       
   102     yield this.loadFromRemote();
       
   103     yield this.deleteFromRemote();
       
   104 
       
   105     let localObjInst;
       
   106 
       
   107     // delete remote obj
       
   108     for(localObjInst of this.localDiffs.get('deleted').values()) {
       
   109 
       
   110       try {
       
   111         yield this.client.delete(this.getRemoteDeleteUrl(localObjInst));
       
   112       } catch(err) {
       
   113         if(err.status !== 404) {
       
   114           //TODO: better error handling ???
       
   115           console.log("error whe deleting object", err);
       
   116         }
       
   117         // otherwise, this is ok
       
   118       }
       
   119 
       
   120       yield put(this.doDeleteLocalObj(localObjInst.get('_id')));
       
   121     }
       
   122 
       
   123     for(localObjInst of this.localDiffs.get('created').values()) {
       
   124       const remoteData = this.getRemoteData(localObjInst);
       
   125       //TODO: SET VERSION !!!!
       
   126       yield this.client.post(this.getRemoteCreateUrl(localObjInst), remoteData);
       
   127       yield put(this.resetLocalObj(localObjInst));
       
   128     }
       
   129 
       
   130     for(localObjInst of this.localDiffs.get('updated').values()) {
       
   131       const remoteData = this.getRemoteData(localObjInst);
       
   132       //TODO: SET VERSION !!!!
       
   133       yield this.client.put(this.getRemoteUpdateUrl(localObjInst), remoteData);
       
   134       yield put(this.resetLocalObj(localObjInst));
       
   135     }
       
   136 
       
   137   }
       
   138 }
       
   139 
       
   140 export default SyncMixin;