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.
This commit is contained in:
infinite-persistence 2021-09-20 10:30:23 +08:00
parent 7515ed2704
commit 64effb4679
No known key found for this signature in database
GPG key ID: B9C3252EDC3D0AA0
4 changed files with 45 additions and 19 deletions

View file

@ -26,6 +26,8 @@ declare type LivestreamState = {
viewersById: {},
fetchingActiveLivestreams: boolean,
activeLivestreams: ?LivestreamInfo,
activeLivestreamsLastFetchedDate: number,
activeLivestreamsLastFetchedOptions: {},
}
declare type LivestreamInfo = {

View file

@ -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';

View file

@ -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<string> = ['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 });
});
};
};

View file

@ -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