client/src/sagas/networkSaga.js
author ymh <ymh.work@gmail.com>
Mon, 26 Jun 2017 16:05:47 +0200
changeset 88 2a861fed6bde
parent 87 dbcee57de2c6
child 97 69eaef18b01b
permissions -rw-r--r--
Deauthenticate user if refresh was not possible (session expired or total delta reached)
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
87
dbcee57de2c6 Add first implementation of network monitor
ymh <ymh.work@gmail.com>
parents:
diff changeset
     1
import * as types from '../constants/actionTypes';
dbcee57de2c6 Add first implementation of network monitor
ymh <ymh.work@gmail.com>
parents:
diff changeset
     2
import { all, call, fork, race, take, cancelled, put, select } from 'redux-saga/effects'
dbcee57de2c6 Add first implementation of network monitor
ymh <ymh.work@gmail.com>
parents:
diff changeset
     3
import config from '../config';
dbcee57de2c6 Add first implementation of network monitor
ymh <ymh.work@gmail.com>
parents:
diff changeset
     4
dbcee57de2c6 Add first implementation of network monitor
ymh <ymh.work@gmail.com>
parents:
diff changeset
     5
// Utility function to delay effects
dbcee57de2c6 Add first implementation of network monitor
ymh <ymh.work@gmail.com>
parents:
diff changeset
     6
function delay(millis) {
dbcee57de2c6 Add first implementation of network monitor
ymh <ymh.work@gmail.com>
parents:
diff changeset
     7
    const promise = new Promise(resolve => {
dbcee57de2c6 Add first implementation of network monitor
ymh <ymh.work@gmail.com>
parents:
diff changeset
     8
        setTimeout(() => resolve(true), millis)
dbcee57de2c6 Add first implementation of network monitor
ymh <ymh.work@gmail.com>
parents:
diff changeset
     9
    });
dbcee57de2c6 Add first implementation of network monitor
ymh <ymh.work@gmail.com>
parents:
diff changeset
    10
    return promise;
dbcee57de2c6 Add first implementation of network monitor
ymh <ymh.work@gmail.com>
parents:
diff changeset
    11
}
dbcee57de2c6 Add first implementation of network monitor
ymh <ymh.work@gmail.com>
parents:
diff changeset
    12
dbcee57de2c6 Add first implementation of network monitor
ymh <ymh.work@gmail.com>
parents:
diff changeset
    13
function pingServer(client, token) {
dbcee57de2c6 Add first implementation of network monitor
ymh <ymh.work@gmail.com>
parents:
diff changeset
    14
  if(token) {
dbcee57de2c6 Add first implementation of network monitor
ymh <ymh.work@gmail.com>
parents:
diff changeset
    15
    const timeout = new Promise((resolve, reject) => {
dbcee57de2c6 Add first implementation of network monitor
ymh <ymh.work@gmail.com>
parents:
diff changeset
    16
      setTimeout(reject, config.networkStatusTimeout, 'request timed out');
dbcee57de2c6 Add first implementation of network monitor
ymh <ymh.work@gmail.com>
parents:
diff changeset
    17
    });
dbcee57de2c6 Add first implementation of network monitor
ymh <ymh.work@gmail.com>
parents:
diff changeset
    18
    return Promise
dbcee57de2c6 Add first implementation of network monitor
ymh <ymh.work@gmail.com>
parents:
diff changeset
    19
      .race([timeout, client.post('/api/auth/refresh/', { token })]);
dbcee57de2c6 Add first implementation of network monitor
ymh <ymh.work@gmail.com>
parents:
diff changeset
    20
  } else {
dbcee57de2c6 Add first implementation of network monitor
ymh <ymh.work@gmail.com>
parents:
diff changeset
    21
    return Promise.reject({ error: 'No token in the store'})
dbcee57de2c6 Add first implementation of network monitor
ymh <ymh.work@gmail.com>
parents:
diff changeset
    22
  }
dbcee57de2c6 Add first implementation of network monitor
ymh <ymh.work@gmail.com>
parents:
diff changeset
    23
}
dbcee57de2c6 Add first implementation of network monitor
ymh <ymh.work@gmail.com>
parents:
diff changeset
    24
dbcee57de2c6 Add first implementation of network monitor
ymh <ymh.work@gmail.com>
parents:
diff changeset
    25
// Fetch data every 20 seconds
dbcee57de2c6 Add first implementation of network monitor
ymh <ymh.work@gmail.com>
parents:
diff changeset
    26
function* pollData(context) {
dbcee57de2c6 Add first implementation of network monitor
ymh <ymh.work@gmail.com>
parents:
diff changeset
    27
  try {
dbcee57de2c6 Add first implementation of network monitor
ymh <ymh.work@gmail.com>
parents:
diff changeset
    28
    yield call(delay, config.networkStatusInterval);
dbcee57de2c6 Add first implementation of network monitor
ymh <ymh.work@gmail.com>
parents:
diff changeset
    29
    const token = yield select(state => state.token);
dbcee57de2c6 Add first implementation of network monitor
ymh <ymh.work@gmail.com>
parents:
diff changeset
    30
    const res = yield pingServer(context.client, token);
dbcee57de2c6 Add first implementation of network monitor
ymh <ymh.work@gmail.com>
parents:
diff changeset
    31
    yield call(context.callback, true);
dbcee57de2c6 Add first implementation of network monitor
ymh <ymh.work@gmail.com>
parents:
diff changeset
    32
    yield put({
dbcee57de2c6 Add first implementation of network monitor
ymh <ymh.work@gmail.com>
parents:
diff changeset
    33
      type: types.AUTH_STORE_TOKEN_ASYNC,
dbcee57de2c6 Add first implementation of network monitor
ymh <ymh.work@gmail.com>
parents:
diff changeset
    34
      token: res.token,
dbcee57de2c6 Add first implementation of network monitor
ymh <ymh.work@gmail.com>
parents:
diff changeset
    35
    });
dbcee57de2c6 Add first implementation of network monitor
ymh <ymh.work@gmail.com>
parents:
diff changeset
    36
  } catch (error) {
dbcee57de2c6 Add first implementation of network monitor
ymh <ymh.work@gmail.com>
parents:
diff changeset
    37
    yield call(context.callback, false);
dbcee57de2c6 Add first implementation of network monitor
ymh <ymh.work@gmail.com>
parents:
diff changeset
    38
    // if the error is that there is no token, then we know we have to wait for a login
dbcee57de2c6 Add first implementation of network monitor
ymh <ymh.work@gmail.com>
parents:
diff changeset
    39
    if(error.error && error.error === 'No token in the store') {
dbcee57de2c6 Add first implementation of network monitor
ymh <ymh.work@gmail.com>
parents:
diff changeset
    40
      yield take(types.AUTH_LOGIN_SUCCESS);
88
2a861fed6bde Deauthenticate user if refresh was not possible (session expired or total delta reached)
ymh <ymh.work@gmail.com>
parents: 87
diff changeset
    41
    } else if (error.non_field_errors &&
2a861fed6bde Deauthenticate user if refresh was not possible (session expired or total delta reached)
ymh <ymh.work@gmail.com>
parents: 87
diff changeset
    42
      error.non_field_errors &&
2a861fed6bde Deauthenticate user if refresh was not possible (session expired or total delta reached)
ymh <ymh.work@gmail.com>
parents: 87
diff changeset
    43
      error.non_field_errors.length &&
2a861fed6bde Deauthenticate user if refresh was not possible (session expired or total delta reached)
ymh <ymh.work@gmail.com>
parents: 87
diff changeset
    44
      error.non_field_errors.length > 0 &&
2a861fed6bde Deauthenticate user if refresh was not possible (session expired or total delta reached)
ymh <ymh.work@gmail.com>
parents: 87
diff changeset
    45
      ( error.non_field_errors[0] === 'Signature has expired.' ||
2a861fed6bde Deauthenticate user if refresh was not possible (session expired or total delta reached)
ymh <ymh.work@gmail.com>
parents: 87
diff changeset
    46
        error.non_field_errors[0] === 'Refresh has expired.' )
2a861fed6bde Deauthenticate user if refresh was not possible (session expired or total delta reached)
ymh <ymh.work@gmail.com>
parents: 87
diff changeset
    47
    ) {
2a861fed6bde Deauthenticate user if refresh was not possible (session expired or total delta reached)
ymh <ymh.work@gmail.com>
parents: 87
diff changeset
    48
      yield put({
2a861fed6bde Deauthenticate user if refresh was not possible (session expired or total delta reached)
ymh <ymh.work@gmail.com>
parents: 87
diff changeset
    49
        type: types.AUTH_DEAUTHENTICATE
2a861fed6bde Deauthenticate user if refresh was not possible (session expired or total delta reached)
ymh <ymh.work@gmail.com>
parents: 87
diff changeset
    50
      });
87
dbcee57de2c6 Add first implementation of network monitor
ymh <ymh.work@gmail.com>
parents:
diff changeset
    51
    }
dbcee57de2c6 Add first implementation of network monitor
ymh <ymh.work@gmail.com>
parents:
diff changeset
    52
  } finally {
dbcee57de2c6 Add first implementation of network monitor
ymh <ymh.work@gmail.com>
parents:
diff changeset
    53
    if (yield cancelled()) {
dbcee57de2c6 Add first implementation of network monitor
ymh <ymh.work@gmail.com>
parents:
diff changeset
    54
      // pollDate cancelled
dbcee57de2c6 Add first implementation of network monitor
ymh <ymh.work@gmail.com>
parents:
diff changeset
    55
      // if there is a token : this was a LOGIN, set status to ok
dbcee57de2c6 Add first implementation of network monitor
ymh <ymh.work@gmail.com>
parents:
diff changeset
    56
      // if there is no token : this was a LOGOUT, set status to ko and wait for login
dbcee57de2c6 Add first implementation of network monitor
ymh <ymh.work@gmail.com>
parents:
diff changeset
    57
      const token = yield select(state => state.token);
dbcee57de2c6 Add first implementation of network monitor
ymh <ymh.work@gmail.com>
parents:
diff changeset
    58
      if(token) {
dbcee57de2c6 Add first implementation of network monitor
ymh <ymh.work@gmail.com>
parents:
diff changeset
    59
        yield call(context.callback, true);
dbcee57de2c6 Add first implementation of network monitor
ymh <ymh.work@gmail.com>
parents:
diff changeset
    60
      } else {
dbcee57de2c6 Add first implementation of network monitor
ymh <ymh.work@gmail.com>
parents:
diff changeset
    61
        yield call(context.callback, false);
dbcee57de2c6 Add first implementation of network monitor
ymh <ymh.work@gmail.com>
parents:
diff changeset
    62
        yield take(types.AUTH_LOGIN_SUCCESS);
dbcee57de2c6 Add first implementation of network monitor
ymh <ymh.work@gmail.com>
parents:
diff changeset
    63
      }
dbcee57de2c6 Add first implementation of network monitor
ymh <ymh.work@gmail.com>
parents:
diff changeset
    64
    }
dbcee57de2c6 Add first implementation of network monitor
ymh <ymh.work@gmail.com>
parents:
diff changeset
    65
  }
dbcee57de2c6 Add first implementation of network monitor
ymh <ymh.work@gmail.com>
parents:
diff changeset
    66
}
dbcee57de2c6 Add first implementation of network monitor
ymh <ymh.work@gmail.com>
parents:
diff changeset
    67
dbcee57de2c6 Add first implementation of network monitor
ymh <ymh.work@gmail.com>
parents:
diff changeset
    68
// Wait for successful response, then fire another request
dbcee57de2c6 Add first implementation of network monitor
ymh <ymh.work@gmail.com>
parents:
diff changeset
    69
// Cancel polling if user logs out or log in
dbcee57de2c6 Add first implementation of network monitor
ymh <ymh.work@gmail.com>
parents:
diff changeset
    70
function* watchPollData(context) {
dbcee57de2c6 Add first implementation of network monitor
ymh <ymh.work@gmail.com>
parents:
diff changeset
    71
  while (true) {
dbcee57de2c6 Add first implementation of network monitor
ymh <ymh.work@gmail.com>
parents:
diff changeset
    72
    yield race([
dbcee57de2c6 Add first implementation of network monitor
ymh <ymh.work@gmail.com>
parents:
diff changeset
    73
      call(pollData, context),
dbcee57de2c6 Add first implementation of network monitor
ymh <ymh.work@gmail.com>
parents:
diff changeset
    74
      take(types.AUTH_LOGOUT),
dbcee57de2c6 Add first implementation of network monitor
ymh <ymh.work@gmail.com>
parents:
diff changeset
    75
      take(types.AUTH_LOGIN_SUCCESS)
dbcee57de2c6 Add first implementation of network monitor
ymh <ymh.work@gmail.com>
parents:
diff changeset
    76
    ]);
dbcee57de2c6 Add first implementation of network monitor
ymh <ymh.work@gmail.com>
parents:
diff changeset
    77
  }
dbcee57de2c6 Add first implementation of network monitor
ymh <ymh.work@gmail.com>
parents:
diff changeset
    78
}
dbcee57de2c6 Add first implementation of network monitor
ymh <ymh.work@gmail.com>
parents:
diff changeset
    79
dbcee57de2c6 Add first implementation of network monitor
ymh <ymh.work@gmail.com>
parents:
diff changeset
    80
// Daemonize tasks in parallel
dbcee57de2c6 Add first implementation of network monitor
ymh <ymh.work@gmail.com>
parents:
diff changeset
    81
export default function* root(baseContext) {
dbcee57de2c6 Add first implementation of network monitor
ymh <ymh.work@gmail.com>
parents:
diff changeset
    82
  const actionRes = yield take(types.OFFLINE_CONFIG_INITIALIZED);
dbcee57de2c6 Add first implementation of network monitor
ymh <ymh.work@gmail.com>
parents:
diff changeset
    83
  const context = {...baseContext, ...actionRes.additionalContext};
dbcee57de2c6 Add first implementation of network monitor
ymh <ymh.work@gmail.com>
parents:
diff changeset
    84
  yield all([
dbcee57de2c6 Add first implementation of network monitor
ymh <ymh.work@gmail.com>
parents:
diff changeset
    85
    fork(watchPollData, context)
dbcee57de2c6 Add first implementation of network monitor
ymh <ymh.work@gmail.com>
parents:
diff changeset
    86
    // other watchers here
dbcee57de2c6 Add first implementation of network monitor
ymh <ymh.work@gmail.com>
parents:
diff changeset
    87
  ]);
dbcee57de2c6 Add first implementation of network monitor
ymh <ymh.work@gmail.com>
parents:
diff changeset
    88
}