From 64effb46792dc20ab7966e7a221331123cce5a2e Mon Sep 17 00:00:00 2001 From: infinite-persistence Date: Mon, 20 Sep 2021 10:30:23 +0800 Subject: [PATCH] doFetchActiveLivestreams: add interval and options checking - Added a default minimum of 5 minutes between fetches. Clients can bypass this through `forceFetch` if needed. - We'll need to support different 'orderBy', so adding an "options check" when determining if we just made the same fetch. --- flow-typed/livestream.js | 2 ++ ui/constants/action_types.js | 1 + ui/redux/actions/livestream.js | 49 +++++++++++++++++++++------------ ui/redux/reducers/livestream.js | 12 ++++++-- 4 files changed, 45 insertions(+), 19 deletions(-) diff --git a/flow-typed/livestream.js b/flow-typed/livestream.js index 63f1dd6a7..9bee62676 100644 --- a/flow-typed/livestream.js +++ b/flow-typed/livestream.js @@ -26,6 +26,8 @@ declare type LivestreamState = { viewersById: {}, fetchingActiveLivestreams: boolean, activeLivestreams: ?LivestreamInfo, + activeLivestreamsLastFetchedDate: number, + activeLivestreamsLastFetchedOptions: {}, } declare type LivestreamInfo = { diff --git a/ui/constants/action_types.js b/ui/constants/action_types.js index 6baee5377..17748007e 100644 --- a/ui/constants/action_types.js +++ b/ui/constants/action_types.js @@ -354,4 +354,5 @@ export const FETCH_NO_SOURCE_CLAIMS_FAILED = 'FETCH_NO_SOURCE_CLAIMS_FAILED'; export const VIEWERS_RECEIVED = 'VIEWERS_RECEIVED'; export const FETCH_ACTIVE_LIVESTREAMS_STARTED = 'FETCH_ACTIVE_LIVESTREAMS_STARTED'; export const FETCH_ACTIVE_LIVESTREAMS_FAILED = 'FETCH_ACTIVE_LIVESTREAMS_FAILED'; +export const FETCH_ACTIVE_LIVESTREAMS_SKIPPED = 'FETCH_ACTIVE_LIVESTREAMS_SKIPPED'; export const FETCH_ACTIVE_LIVESTREAMS_COMPLETED = 'FETCH_ACTIVE_LIVESTREAMS_COMPLETED'; diff --git a/ui/redux/actions/livestream.js b/ui/redux/actions/livestream.js index 9ab7051a4..3f94b5a4c 100644 --- a/ui/redux/actions/livestream.js +++ b/ui/redux/actions/livestream.js @@ -33,19 +33,34 @@ export const doFetchNoSourceClaims = (channelId: string) => async (dispatch: Dis } }; -export const doFetchActiveLivestreams = () => { - return async (dispatch: Dispatch) => { - dispatch({ - type: ACTIONS.FETCH_ACTIVE_LIVESTREAMS_STARTED, - }); +const FETCH_ACTIVE_LIVESTREAMS_MIN_INTERVAL_MS = 5 * 60 * 1000; + +export const doFetchActiveLivestreams = ( + orderBy: Array = ['release_time'], + pageSize: number = 50, + forceFetch: boolean = false +) => { + return async (dispatch: Dispatch, getState: GetState) => { + const state = getState(); + const now = Date.now(); + const timeDelta = now - state.livestream.activeLivestreamsLastFetchedDate; + + const prevOptions = state.livestream.activeLivestreamsLastFetchedOptions; + const nextOptions = { page_size: pageSize, order_by: orderBy }; + const sameOptions = JSON.stringify(prevOptions) === JSON.stringify(nextOptions); + + if (!forceFetch && sameOptions && timeDelta < FETCH_ACTIVE_LIVESTREAMS_MIN_INTERVAL_MS) { + dispatch({ type: ACTIONS.FETCH_ACTIVE_LIVESTREAMS_SKIPPED }); + return; + } + + dispatch({ type: ACTIONS.FETCH_ACTIVE_LIVESTREAMS_STARTED }); fetch(LIVESTREAM_LIVE_API) .then((res) => res.json()) .then((res) => { if (!res.data) { - dispatch({ - type: ACTIONS.FETCH_ACTIVE_LIVESTREAMS_FAILED, - }); + dispatch({ type: ACTIONS.FETCH_ACTIVE_LIVESTREAMS_FAILED }); return; } @@ -64,11 +79,11 @@ export const doFetchActiveLivestreams = () => { // live. The UI usually just wants to report the latest claim, so we // query that store it in `latestClaimUri`. doClaimSearch({ - page_size: 50, + page_size: nextOptions.page_size, has_no_source: true, channel_ids: Object.keys(activeLivestreams), claim_type: ['stream'], - order_by: ['release_time'], // ** + order_by: nextOptions.order_by, // ** limit_claims_per_channel: 1, // ** no_totals: true, }) @@ -88,19 +103,19 @@ export const doFetchActiveLivestreams = () => { dispatch({ type: ACTIONS.FETCH_ACTIVE_LIVESTREAMS_COMPLETED, - data: activeLivestreams, + data: { + activeLivestreams, + activeLivestreamsLastFetchedDate: now, + activeLivestreamsLastFetchedOptions: nextOptions, + }, }); }) .catch(() => { - dispatch({ - type: ACTIONS.FETCH_ACTIVE_LIVESTREAMS_FAILED, - }); + dispatch({ type: ACTIONS.FETCH_ACTIVE_LIVESTREAMS_FAILED }); }); }) .catch((err) => { - dispatch({ - type: ACTIONS.FETCH_ACTIVE_LIVESTREAMS_FAILED, - }); + dispatch({ type: ACTIONS.FETCH_ACTIVE_LIVESTREAMS_FAILED }); }); }; }; diff --git a/ui/redux/reducers/livestream.js b/ui/redux/reducers/livestream.js index 932be2cb9..7a5d8af84 100644 --- a/ui/redux/reducers/livestream.js +++ b/ui/redux/reducers/livestream.js @@ -7,6 +7,8 @@ const defaultState: LivestreamState = { viewersById: {}, fetchingActiveLivestreams: false, activeLivestreams: null, + activeLivestreamsLastFetchedDate: 0, + activeLivestreamsLastFetchedOptions: {}, }; export default handleActions( @@ -45,8 +47,14 @@ export default handleActions( return { ...state, fetchingActiveLivestreams: false }; }, [ACTIONS.FETCH_ACTIVE_LIVESTREAMS_COMPLETED]: (state: LivestreamState, action: any) => { - const activeLivestreams: LivestreamInfo = action.data; - return { ...state, fetchingActiveLivestreams: false, activeLivestreams }; + const { activeLivestreams, activeLivestreamsLastFetchedDate, activeLivestreamsLastFetchedOptions } = action.data; + return { + ...state, + fetchingActiveLivestreams: false, + activeLivestreams, + activeLivestreamsLastFetchedDate, + activeLivestreamsLastFetchedOptions, + }; }, }, defaultState