feat(updates): Store updates if the server is not responding

This commit is contained in:
Stuart Taylor
2018-07-26 14:37:10 +01:00
committed by Mrugesh Mohapatra
parent 54e14b9433
commit e4e41e6fe3
14 changed files with 312 additions and 78 deletions

View File

@@ -0,0 +1,74 @@
import { merge } from 'rxjs/observable/merge';
import { empty } from 'rxjs/observable/empty';
import {
tap,
filter,
map,
ignoreElements,
switchMap,
catchError
} from 'rxjs/operators';
import { ofType } from 'redux-observable';
import store from 'store';
import uuid from 'uuid/v4';
import { types, onlineStatusChange, isOnlineSelector } from './';
import postUpdate$ from '../../templates/Challenges/utils/postUpdate$';
const key = 'fcc-failed-updates';
function delay(time = 0, fn) {
return setTimeout(fn, time);
}
function failedUpdateEpic(action$, { getState }) {
const storeUpdates = action$.pipe(
ofType(types.updateFailed),
tap(({ payload }) => {
const failures = store.get(key) || [];
payload.id = uuid();
store.set(key, [...failures, payload]);
}),
map(() => onlineStatusChange(false))
);
const flushUpdates = action$.pipe(
ofType(types.fetchUserComplete, types.updateComplete),
filter(() => store.get(key)),
filter(() => isOnlineSelector(getState())),
tap(() => {
const failures = store.get(key) || [];
let delayTime = 0;
const batch = failures.map(update => {
delayTime += 300;
// we stagger the updates here so we don't hammer the server
return delay(delayTime, () =>
postUpdate$(update)
.pipe(
switchMap(response => {
if (response && response.message) {
// the request completed successfully
const failures = store.get(key) || [];
const newFailures = failures.filter(x => x.id !== update.id);
store.set(key, newFailures);
}
return empty();
}),
catchError(() => empty())
)
.toPromise()
);
});
Promise.all(batch)
.then(() => console.info('progress updates processed where possible'))
.catch(err =>
console.warn('unable to process progress updates', err.message)
);
}),
ignoreElements()
);
return merge(storeUpdates, flushUpdates);
}
export default failedUpdateEpic;