client/src/sagas/networkSaga.js
changeset 87 dbcee57de2c6
child 88 2a861fed6bde
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/src/sagas/networkSaga.js	Mon Jun 26 15:21:06 2017 +0200
@@ -0,0 +1,79 @@
+import * as types from '../constants/actionTypes';
+import { all, call, fork, race, take, cancelled, put, select } from 'redux-saga/effects'
+import config from '../config';
+
+// Utility function to delay effects
+function delay(millis) {
+    const promise = new Promise(resolve => {
+        setTimeout(() => resolve(true), millis)
+    });
+    return promise;
+}
+
+function pingServer(client, token) {
+  console.log("PING SERVER", token);
+  if(token) {
+    const timeout = new Promise((resolve, reject) => {
+      setTimeout(reject, config.networkStatusTimeout, 'request timed out');
+    });
+    return Promise
+      .race([timeout, client.post('/api/auth/refresh/', { token })]);
+  } else {
+    return Promise.reject({ error: 'No token in the store'})
+  }
+}
+
+// Fetch data every 20 seconds
+function* pollData(context) {
+  try {
+    yield call(delay, config.networkStatusInterval);
+    const token = yield select(state => state.token);
+    const res = yield pingServer(context.client, token);
+    yield call(context.callback, true);
+    yield put({
+      type: types.AUTH_STORE_TOKEN_ASYNC,
+      token: res.token,
+    });
+  } catch (error) {
+    yield call(context.callback, false);
+    // if the error is that there is no token, then we know we have to wait for a login
+    if(error.error && error.error === 'No token in the store') {
+      yield take(types.AUTH_LOGIN_SUCCESS);
+    }
+  } finally {
+    if (yield cancelled()) {
+      // pollDate cancelled
+      // if there is a token : this was a LOGIN, set status to ok
+      // if there is no token : this was a LOGOUT, set status to ko and wait for login
+      const token = yield select(state => state.token);
+      if(token) {
+        yield call(context.callback, true);
+      } else {
+        yield call(context.callback, false);
+        yield take(types.AUTH_LOGIN_SUCCESS);
+      }
+    }
+  }
+}
+
+// Wait for successful response, then fire another request
+// Cancel polling if user logs out or log in
+function* watchPollData(context) {
+  while (true) {
+    yield race([
+      call(pollData, context),
+      take(types.AUTH_LOGOUT),
+      take(types.AUTH_LOGIN_SUCCESS)
+    ]);
+  }
+}
+
+// Daemonize tasks in parallel
+export default function* root(baseContext) {
+  const actionRes = yield take(types.OFFLINE_CONFIG_INITIALIZED);
+  const context = {...baseContext, ...actionRes.additionalContext};
+  yield all([
+    fork(watchPollData, context)
+    // other watchers here
+  ]);
+}