shlink-web-client/src/visits/reducers/common.js

61 lines
1.9 KiB
JavaScript
Raw Normal View History

2020-05-10 20:02:58 +03:00
import { flatten, prop, range, splitEvery } from 'ramda';
const ITEMS_PER_PAGE = 5000;
const PARALLEL_REQUESTS_COUNT = 4;
const PARALLEL_STARTING_PAGE = 2;
2020-05-10 20:02:58 +03:00
const isLastPage = ({ currentPage, pagesCount }) => currentPage >= pagesCount;
const calcProgress = (total, current) => current * 100 / total;
2020-05-10 20:02:58 +03:00
export const getVisitsWithLoader = async (visitsLoader, extraFinishActionData, actionMap, dispatch, getState) => {
dispatch({ type: actionMap.start });
const loadVisits = async (page = 1) => {
const { pagination, data } = await visitsLoader(page, ITEMS_PER_PAGE);
// If pagination was not returned, then this is an old shlink version. Just return data
if (!pagination || isLastPage(pagination)) {
return data;
}
// If there are more pages, make requests in blocks of 4
const pagesRange = range(PARALLEL_STARTING_PAGE, pagination.pagesCount + 1);
const pagesBlocks = splitEvery(PARALLEL_REQUESTS_COUNT, pagesRange);
2020-05-10 20:02:58 +03:00
if (pagination.pagesCount - 1 > PARALLEL_REQUESTS_COUNT) {
2020-05-10 20:02:58 +03:00
dispatch({ type: actionMap.large });
}
return data.concat(await loadPagesBlocks(pagesBlocks));
};
const loadPagesBlocks = async (pagesBlocks, index = 0) => {
const { shortUrlVisits: { cancelLoad } } = getState();
if (cancelLoad) {
return [];
}
const data = await loadVisitsInParallel(pagesBlocks[index]);
dispatch({ type: actionMap.progress, progress: calcProgress(pagesBlocks.length, index + PARALLEL_STARTING_PAGE) });
2020-05-10 20:02:58 +03:00
if (index < pagesBlocks.length - 1) {
return data.concat(await loadPagesBlocks(pagesBlocks, index + 1));
}
return data;
};
const loadVisitsInParallel = (pages) =>
Promise.all(pages.map((page) => visitsLoader(page, ITEMS_PER_PAGE).then(prop('data')))).then(flatten);
try {
const visits = await loadVisits();
dispatch({ ...extraFinishActionData, visits, type: actionMap.finish });
} catch (e) {
dispatch({ type: actionMap.error });
}
};