Add a better solution for 304 browser bug + update naming conventions to better articulate what's happening (#603)

This commit is contained in:
Dan Peterson 2022-01-06 11:49:49 -06:00 committed by GitHub
parent 1eaa172a1b
commit bc38466abf
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 53 additions and 41 deletions

View file

@ -13,7 +13,7 @@ import { makeSelectChannelIsMuted } from 'redux/selectors/blocked';
import { withRouter } from 'react-router'; import { withRouter } from 'react-router';
import { selectUserVerifiedEmail } from 'redux/selectors/user'; import { selectUserVerifiedEmail } from 'redux/selectors/user';
import { selectClientSetting, selectShowMatureContent } from 'redux/selectors/settings'; import { selectClientSetting, selectShowMatureContent } from 'redux/selectors/settings';
import { doFetchActiveLivestream } from 'redux/actions/livestream'; import { doFetchChannelLiveStatus } from 'redux/actions/livestream';
import { selectActiveLivestreamForChannel, selectActiveLivestreamInitialized } from 'redux/selectors/livestream'; import { selectActiveLivestreamForChannel, selectActiveLivestreamInitialized } from 'redux/selectors/livestream';
import { getChannelIdFromClaim } from 'util/claim'; import { getChannelIdFromClaim } from 'util/claim';
import ChannelContent from './view'; import ChannelContent from './view';
@ -42,7 +42,7 @@ const select = (state, props) => {
const perform = (dispatch) => ({ const perform = (dispatch) => ({
doResolveUris: (uris, returnCachedUris) => dispatch(doResolveUris(uris, returnCachedUris)), doResolveUris: (uris, returnCachedUris) => dispatch(doResolveUris(uris, returnCachedUris)),
doFetchActiveLivestream: (channelID) => dispatch(doFetchActiveLivestream(channelID)), doFetchChannelLiveStatus: (channelID) => dispatch(doFetchChannelLiveStatus(channelID)),
}); });
export default withRouter(connect(select, perform)(ChannelContent)); export default withRouter(connect(select, perform)(ChannelContent));

View file

@ -37,7 +37,7 @@ type Props = {
doResolveUris: (Array<string>, boolean) => void, doResolveUris: (Array<string>, boolean) => void,
claimType: string, claimType: string,
empty?: string, empty?: string,
doFetchActiveLivestream: (string) => void, doFetchChannelLiveStatus: (string) => void,
activeLivestreamForChannel: any, activeLivestreamForChannel: any,
activeLivestreamInitialized: boolean, activeLivestreamInitialized: boolean,
}; };
@ -59,7 +59,7 @@ function ChannelContent(props: Props) {
doResolveUris, doResolveUris,
claimType, claimType,
empty, empty,
doFetchActiveLivestream, doFetchChannelLiveStatus,
activeLivestreamForChannel, activeLivestreamForChannel,
activeLivestreamInitialized, activeLivestreamInitialized,
} = props; } = props;
@ -126,10 +126,10 @@ function ChannelContent(props: Props) {
// Find out current channels status + active live claim. // Find out current channels status + active live claim.
React.useEffect(() => { React.useEffect(() => {
doFetchActiveLivestream(claimId); doFetchChannelLiveStatus(claimId);
const intervalId = setInterval(() => doFetchActiveLivestream(claimId), 30000); const intervalId = setInterval(() => doFetchChannelLiveStatus(claimId), 30000);
return () => clearInterval(intervalId); return () => clearInterval(intervalId);
}, [claimId, doFetchActiveLivestream]); }, [claimId, doFetchChannelLiveStatus]);
const showScheduledLiveStreams = claimType !== 'collection'; // ie. not on the playlist page. const showScheduledLiveStreams = claimType !== 'collection'; // ie. not on the playlist page.

View file

@ -477,9 +477,8 @@ 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_SKIPPED = 'FETCH_ACTIVE_LIVESTREAMS_SKIPPED';
export const FETCH_ACTIVE_LIVESTREAMS_COMPLETED = 'FETCH_ACTIVE_LIVESTREAMS_COMPLETED'; export const FETCH_ACTIVE_LIVESTREAMS_COMPLETED = 'FETCH_ACTIVE_LIVESTREAMS_COMPLETED';
export const FETCH_ACTIVE_LIVESTREAM_FAILED = 'FETCH_ACTIVE_LIVESTREAMS_FAILED'; export const ADD_CHANNEL_TO_ACTIVE_LIVESTREAMS = 'ADD_CHANNEL_TO_ACTIVE_LIVESTREAMS';
export const FETCH_ACTIVE_LIVESTREAM_COMPLETED = 'FETCH_ACTIVE_LIVESTREAM_COMPLETED'; export const REMOVE_CHANNEL_FROM_ACTIVE_LIVESTREAMS = 'REMOVE_CHANNEL_FROM_ACTIVE_LIVESTREAMS';
export const FETCH_ACTIVE_LIVESTREAM_FINISHED = 'FETCH_ACTIVE_LIVESTREAM_FINISHED';
// Blacklist // Blacklist
export const FETCH_BLACK_LISTED_CONTENT_STARTED = 'FETCH_BLACK_LISTED_CONTENT_STARTED'; export const FETCH_BLACK_LISTED_CONTENT_STARTED = 'FETCH_BLACK_LISTED_CONTENT_STARTED';

View file

@ -7,7 +7,7 @@ import { DISABLE_COMMENTS_TAG } from 'constants/tags';
import { doCommentSocketConnect, doCommentSocketDisconnect } from 'redux/actions/websocket'; import { doCommentSocketConnect, doCommentSocketDisconnect } from 'redux/actions/websocket';
import { getChannelIdFromClaim } from 'util/claim'; import { getChannelIdFromClaim } from 'util/claim';
import { selectActiveLivestreamForChannel, selectActiveLivestreamInitialized } from 'redux/selectors/livestream'; import { selectActiveLivestreamForChannel, selectActiveLivestreamInitialized } from 'redux/selectors/livestream';
import { doFetchActiveLivestream } from 'redux/actions/livestream'; import { doFetchChannelLiveStatus } from 'redux/actions/livestream';
import LivestreamPage from './view'; import LivestreamPage from './view';
const select = (state, props) => { const select = (state, props) => {
@ -26,7 +26,7 @@ const perform = {
doUserSetReferrer, doUserSetReferrer,
doCommentSocketConnect, doCommentSocketConnect,
doCommentSocketDisconnect, doCommentSocketDisconnect,
doFetchActiveLivestream, doFetchChannelLiveStatus,
}; };
export default connect(select, perform)(LivestreamPage); export default connect(select, perform)(LivestreamPage);

View file

@ -19,7 +19,7 @@ type Props = {
chatDisabled: boolean, chatDisabled: boolean,
doCommentSocketConnect: (string, string) => void, doCommentSocketConnect: (string, string) => void,
doCommentSocketDisconnect: (string) => void, doCommentSocketDisconnect: (string) => void,
doFetchActiveLivestream: (string) => void, doFetchChannelLiveStatus: (string) => void,
activeLivestreamForChannel: any, activeLivestreamForChannel: any,
activeLivestreamInitialized: boolean, activeLivestreamInitialized: boolean,
}; };
@ -35,7 +35,7 @@ export default function LivestreamPage(props: Props) {
chatDisabled, chatDisabled,
doCommentSocketConnect, doCommentSocketConnect,
doCommentSocketDisconnect, doCommentSocketDisconnect,
doFetchActiveLivestream, doFetchChannelLiveStatus,
activeLivestreamForChannel, activeLivestreamForChannel,
activeLivestreamInitialized, activeLivestreamInitialized,
} = props; } = props;
@ -67,10 +67,10 @@ export default function LivestreamPage(props: Props) {
// Find out current channels status + active live claim. // Find out current channels status + active live claim.
React.useEffect(() => { React.useEffect(() => {
doFetchActiveLivestream(livestreamChannelId); doFetchChannelLiveStatus(livestreamChannelId);
const intervalId = setInterval(() => doFetchActiveLivestream(livestreamChannelId), 30000); const intervalId = setInterval(() => doFetchChannelLiveStatus(livestreamChannelId), 30000);
return () => clearInterval(intervalId); return () => clearInterval(intervalId);
}, [livestreamChannelId, doFetchActiveLivestream]); }, [livestreamChannelId, doFetchChannelLiveStatus]);
const [activeStreamUri, setActiveStreamUri] = React.useState(false); const [activeStreamUri, setActiveStreamUri] = React.useState(false);

View file

@ -4,6 +4,16 @@ import { doClaimSearch } from 'redux/actions/claims';
import { LIVESTREAM_LIVE_API, LIVESTREAM_STARTS_SOON_BUFFER } from 'constants/livestream'; import { LIVESTREAM_LIVE_API, LIVESTREAM_STARTS_SOON_BUFFER } from 'constants/livestream';
import moment from 'moment'; import moment from 'moment';
const LiveStatus = Object.freeze({
LIVE: 'LIVE',
NOT_LIVE: 'NOT_LIVE',
UNKNOWN: 'UNKNOWN',
});
type LiveStatusType = $Keys<typeof LiveStatus>;
type LiveChannelStatus = { channelStatus: LiveStatusType, channelData?: LivestreamInfo };
export const doFetchNoSourceClaims = (channelId: string) => async (dispatch: Dispatch, getState: GetState) => { export const doFetchNoSourceClaims = (channelId: string) => async (dispatch: Dispatch, getState: GetState) => {
dispatch({ dispatch({
type: ACTIONS.FETCH_NO_SOURCE_CLAIMS_STARTED, type: ACTIONS.FETCH_NO_SOURCE_CLAIMS_STARTED,
@ -48,23 +58,22 @@ const transformLivestreamData = (data: Array<any>): LivestreamInfo => {
}, {}); }, {});
}; };
const fetchLiveChannels = async () => { const fetchLiveChannels = async (): Promise<LivestreamInfo> => {
const response = await fetch(LIVESTREAM_LIVE_API); const response = await fetch(LIVESTREAM_LIVE_API);
const json = await response.json(); const json = await response.json();
if (!json.data) throw new Error(); if (!json.data) throw new Error();
return transformLivestreamData(json.data); return transformLivestreamData(json.data);
}; };
const fetchLiveChannel = async (channelId: string) => { const fetchLiveChannel = async (channelId: string): Promise<LiveChannelStatus> => {
const response = await fetch(`${LIVESTREAM_LIVE_API}/${channelId}`);
let json;
try { try {
json = await response.json(); const response = await fetch(`${LIVESTREAM_LIVE_API}/${channelId}`);
const json = await response.json();
if (json.data?.live === false) return { channelStatus: LiveStatus.NOT_LIVE };
return { channelStatus: LiveStatus.LIVE, channelData: transformLivestreamData([json.data]) };
} catch { } catch {
throw new Error('Error handling live API response'); return { channelStatus: LiveStatus.UNKNOWN };
} }
if (!(json.data && json.data.live)) throw new Error();
return transformLivestreamData([json.data]);
}; };
const filterUpcomingLiveStreamClaims = (upcomingClaims) => { const filterUpcomingLiveStreamClaims = (upcomingClaims) => {
@ -164,25 +173,29 @@ const findActiveStreams = async (channelIDs: Array<string>, orderBy: Array<strin
return determineLiveClaim(allClaims, liveChannels); return determineLiveClaim(allClaims, liveChannels);
}; };
export const doFetchActiveLivestream = (channelId: string) => { export const doFetchChannelLiveStatus = (channelId: string) => {
return async (dispatch: Dispatch) => { return async (dispatch: Dispatch) => {
try { try {
const liveChannel = await fetchLiveChannel(channelId); const { channelStatus, channelData } = await fetchLiveChannel(channelId);
const currentlyLiveClaims = await findActiveStreams([channelId], ['release_time'], liveChannel, dispatch);
if (channelStatus === LiveStatus.NOT_LIVE) {
dispatch({ type: ACTIONS.REMOVE_CHANNEL_FROM_ACTIVE_LIVESTREAMS, data: { channelId } });
return;
}
if (channelStatus === LiveStatus.UNKNOWN) {
return;
}
const currentlyLiveClaims = await findActiveStreams([channelId], ['release_time'], channelData, dispatch);
const liveClaim = currentlyLiveClaims[channelId]; const liveClaim = currentlyLiveClaims[channelId];
liveChannel[channelId].claimId = liveClaim.stream.claim_id; if (channelData && liveClaim) {
liveChannel[channelId].claimUri = liveClaim.stream.canonical_url; channelData[channelId].claimId = liveClaim.stream.claim_id;
channelData[channelId].claimUri = liveClaim.stream.canonical_url;
dispatch({ dispatch({ type: ACTIONS.ADD_CHANNEL_TO_ACTIVE_LIVESTREAMS, data: { ...channelData } });
type: ACTIONS.FETCH_ACTIVE_LIVESTREAM_COMPLETED, }
data: {
...liveChannel,
},
});
} catch (err) { } catch (err) {
if (err.message === 'Error handling live API response') return; dispatch({ type: ACTIONS.REMOVE_CHANNEL_FROM_ACTIVE_LIVESTREAMS, data: { channelId } });
dispatch({ type: ACTIONS.FETCH_ACTIVE_LIVESTREAM_FAILED, data: { channelId } });
} }
}; };
}; };

View file

@ -58,11 +58,11 @@ export default handleActions(
activeLivestreamsLastFetchedOptions, activeLivestreamsLastFetchedOptions,
}; };
}, },
[ACTIONS.FETCH_ACTIVE_LIVESTREAM_COMPLETED]: (state: LivestreamState, action: any) => { [ACTIONS.ADD_CHANNEL_TO_ACTIVE_LIVESTREAMS]: (state: LivestreamState, action: any) => {
const activeLivestreams = Object.assign({}, state.activeLivestreams || {}, action.data); const activeLivestreams = Object.assign({}, state.activeLivestreams || {}, action.data);
return { ...state, activeLivestreams, activeLivestreamInitialized: true }; return { ...state, activeLivestreams, activeLivestreamInitialized: true };
}, },
[ACTIONS.FETCH_ACTIVE_LIVESTREAM_FAILED]: (state: LivestreamState, action: any) => { [ACTIONS.REMOVE_CHANNEL_FROM_ACTIVE_LIVESTREAMS]: (state: LivestreamState, action: any) => {
const activeLivestreams = state.activeLivestreams; const activeLivestreams = state.activeLivestreams;
if (activeLivestreams) delete activeLivestreams[action.data.channelId]; if (activeLivestreams) delete activeLivestreams[action.data.channelId];
return { ...state, activeLivestreams: Object.assign({}, activeLivestreams), activeLivestreamInitialized: true }; return { ...state, activeLivestreams: Object.assign({}, activeLivestreams), activeLivestreamInitialized: true };