client/src/sagas/BaseSyncronizer.js
author ymh <ymh.work@gmail.com>
Fri, 28 Jul 2017 19:40:35 +0200
changeset 129 d48946d164c6
child 168 ea92f4fe783d
permissions -rw-r--r--
Add a first version of synchronisation Remove redux-offline dependency make the redux state fully immutable TODO: better error management TODO: make syncronization work automatically
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
129
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
     1
import { put } from 'redux-saga/effects'
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
     2
import Immutable from 'immutable';
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
     3
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
     4
export const SyncMixin = Base => class extends Base {
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
     5
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
     6
  constructor(syncEntries, client) {
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
     7
    super();
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
     8
    this.syncEntries = syncEntries;
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
     9
    this.client = client;
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
    10
    this.localDiffs = null;
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
    11
  }
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
    12
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
    13
  // abstract methods
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
    14
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
    15
  // local diffs (immutable)
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
    16
  // getLocalDiffs()
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
    17
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
    18
  // remote urls
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
    19
  // getRemoteLoadUrl()
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
    20
  // getRemoteDeleteUrl(localObjInst);
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
    21
  // getRemoteCreateUrl(localObjInst)
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
    22
  // getRemoteUpdateUrl(localObjInst)
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
    23
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
    24
  // build remote json message
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
    25
  // getRemoteData(localObjInst)
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
    26
  // getLocalRecord(remoteObj)
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
    27
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
    28
  // actions
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
    29
  // doDeleteLocalObj(localObjId);
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
    30
  // resetLocalObj(localObjInst)
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
    31
  // loadObj(objRecord)
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
    32
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
    33
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
    34
  * loadFromRemote() {
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
    35
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
    36
    const objIds = this.syncEntries
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
    37
      .filter((syncEntry) => syncEntry.action !== 2)
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
    38
      .map((syncEntry) => syncEntry.ext_id);
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
    39
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
    40
    if(objIds.length === 0) {
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
    41
      return ;
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
    42
    }
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
    43
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
    44
    //TODO: manage pagination
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
    45
    const remoteObjs = yield this.client.get(this.getRemoteLoadUrl(), { ext_id__in: objIds.join(',') })
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
    46
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
    47
    for (var remoteObj of remoteObjs.results) {
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
    48
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
    49
      if(this.localDiffs.get('deleted').has(remoteObj.ext_id)) {
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
    50
        // The session has been deleted locally, we will delete it later
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
    51
        continue;
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
    52
      }
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
    53
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
    54
      if(this.localDiffs.get('created').has(remoteObj.ext_id)) {
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
    55
        // The session has been modified both locally and remotely
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
    56
        // the server wins, it will be loaded locally, we must remove it from the list of locally changed sessions
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
    57
        const newCreatedMap = this.localDiffs.get('created').delete(remoteObj.ext_id);
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
    58
        this.localDiffs = this.localDiffs.set('created', newCreatedMap);
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
    59
      }
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
    60
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
    61
      if(this.localDiffs.get('updated').has(remoteObj.ext_id)) {
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
    62
        // The session has been modified both locally and remotely
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
    63
        // the server wins, it will be loaded locally, we must remove it from the list of locally changed sessions
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
    64
        const newModifiedMap = this.localDiffs.get('updated').delete(remoteObj.ext_id);
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
    65
        this.localDiffs = this.localDiffs.set('updated', newModifiedMap);
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
    66
      }
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
    67
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
    68
      let objRecord = this.getLocalRecord(remoteObj);
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
    69
      yield put(this.loadObj(objRecord));
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
    70
    }
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
    71
  }
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
    72
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
    73
  * deleteFromRemote() {
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
    74
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
    75
    const objToDelete = this.syncEntries
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
    76
      .filter((syncObj) => syncObj.action === 2)
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
    77
      .map((syncObj) => syncObj.ext_id);
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
    78
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
    79
    let deleteObjs = this.localDiffs.get('deleted');
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
    80
    let updatedObjs = this.localDiffs.get('updated');
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
    81
    let createdObjs = this.localDiffs.get('created');
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
    82
    for (var objId of objToDelete) {
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
    83
      if(deleteObjs.has(objId)) {
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
    84
        // we remove it from the list of sessions to delete
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
    85
        deleteObjs = deleteObjs.delete(objId);
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
    86
      }
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
    87
      if(updatedObjs.has(objId)) {
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
    88
        updatedObjs = updatedObjs.delete(objId);
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
    89
      }
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
    90
      if(createdObjs.has(objId)) {
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
    91
        createdObjs = createdObjs.delete(objId);
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
    92
      }
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
    93
      yield put(this.doDeleteLocalObj(objId));
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
    94
    }
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
    95
    this.localDiffs = Immutable.Map({created: createdObjs, updated: updatedObjs, deleted: deleteObjs});
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
    96
  }
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
    97
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
    98
  * syncObjects() {
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
    99
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
   100
    this.localDiffs = yield this.getLocalDiffs();
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
   101
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
   102
    yield this.loadFromRemote();
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
   103
    yield this.deleteFromRemote();
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
   104
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
   105
    let localObjInst;
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
   106
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
   107
    // delete remote obj
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
   108
    for(localObjInst of this.localDiffs.get('deleted').values()) {
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
   109
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
   110
      try {
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
   111
        yield this.client.delete(this.getRemoteDeleteUrl(localObjInst));
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
   112
      } catch(err) {
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
   113
        if(err.status !== 404) {
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
   114
          //TODO: better error handling ???
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
   115
          console.log("error whe deleting object", err);
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
   116
        }
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
   117
        // otherwise, this is ok
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
   118
      }
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
   119
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
   120
      yield put(this.doDeleteLocalObj(localObjInst.get('_id')));
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
   121
    }
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
   122
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
   123
    for(localObjInst of this.localDiffs.get('created').values()) {
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
   124
      const remoteData = this.getRemoteData(localObjInst);
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
   125
      //TODO: SET VERSION !!!!
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
   126
      yield this.client.post(this.getRemoteCreateUrl(localObjInst), remoteData);
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
   127
      yield put(this.resetLocalObj(localObjInst));
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
   128
    }
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
   129
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
   130
    for(localObjInst of this.localDiffs.get('updated').values()) {
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
   131
      const remoteData = this.getRemoteData(localObjInst);
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
   132
      //TODO: SET VERSION !!!!
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
   133
      yield this.client.put(this.getRemoteUpdateUrl(localObjInst), remoteData);
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
   134
      yield put(this.resetLocalObj(localObjInst));
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
   135
    }
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
   136
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
   137
  }
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
   138
}
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
   139
d48946d164c6 Add a first version of synchronisation
ymh <ymh.work@gmail.com>
parents:
diff changeset
   140
export default SyncMixin;