|
1 import * as types from '../constants/actionTypes'; |
|
2 import { all, call, fork, race, take, cancelled, put, select } from 'redux-saga/effects' |
|
3 import config from '../config'; |
|
4 |
|
5 // Utility function to delay effects |
|
6 function delay(millis) { |
|
7 const promise = new Promise(resolve => { |
|
8 setTimeout(() => resolve(true), millis) |
|
9 }); |
|
10 return promise; |
|
11 } |
|
12 |
|
13 function pingServer(client, token) { |
|
14 console.log("PING SERVER", token); |
|
15 if(token) { |
|
16 const timeout = new Promise((resolve, reject) => { |
|
17 setTimeout(reject, config.networkStatusTimeout, 'request timed out'); |
|
18 }); |
|
19 return Promise |
|
20 .race([timeout, client.post('/api/auth/refresh/', { token })]); |
|
21 } else { |
|
22 return Promise.reject({ error: 'No token in the store'}) |
|
23 } |
|
24 } |
|
25 |
|
26 // Fetch data every 20 seconds |
|
27 function* pollData(context) { |
|
28 try { |
|
29 yield call(delay, config.networkStatusInterval); |
|
30 const token = yield select(state => state.token); |
|
31 const res = yield pingServer(context.client, token); |
|
32 yield call(context.callback, true); |
|
33 yield put({ |
|
34 type: types.AUTH_STORE_TOKEN_ASYNC, |
|
35 token: res.token, |
|
36 }); |
|
37 } catch (error) { |
|
38 yield call(context.callback, false); |
|
39 // if the error is that there is no token, then we know we have to wait for a login |
|
40 if(error.error && error.error === 'No token in the store') { |
|
41 yield take(types.AUTH_LOGIN_SUCCESS); |
|
42 } |
|
43 } finally { |
|
44 if (yield cancelled()) { |
|
45 // pollDate cancelled |
|
46 // if there is a token : this was a LOGIN, set status to ok |
|
47 // if there is no token : this was a LOGOUT, set status to ko and wait for login |
|
48 const token = yield select(state => state.token); |
|
49 if(token) { |
|
50 yield call(context.callback, true); |
|
51 } else { |
|
52 yield call(context.callback, false); |
|
53 yield take(types.AUTH_LOGIN_SUCCESS); |
|
54 } |
|
55 } |
|
56 } |
|
57 } |
|
58 |
|
59 // Wait for successful response, then fire another request |
|
60 // Cancel polling if user logs out or log in |
|
61 function* watchPollData(context) { |
|
62 while (true) { |
|
63 yield race([ |
|
64 call(pollData, context), |
|
65 take(types.AUTH_LOGOUT), |
|
66 take(types.AUTH_LOGIN_SUCCESS) |
|
67 ]); |
|
68 } |
|
69 } |
|
70 |
|
71 // Daemonize tasks in parallel |
|
72 export default function* root(baseContext) { |
|
73 const actionRes = yield take(types.OFFLINE_CONFIG_INITIALIZED); |
|
74 const context = {...baseContext, ...actionRes.additionalContext}; |
|
75 yield all([ |
|
76 fork(watchPollData, context) |
|
77 // other watchers here |
|
78 ]); |
|
79 } |