Skip to content

Commit

Permalink
feat: add timeout for videos fetch requests
Browse files Browse the repository at this point in the history
  • Loading branch information
AXeL-dev committed Jun 20, 2022
1 parent f03c47d commit c6dddc6
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 4 deletions.
28 changes: 26 additions & 2 deletions src/store/services/youtube/api.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react';
import {
createApi,
FetchArgs,
fetchBaseQuery,
} from '@reduxjs/toolkit/query/react';
import { BaseQueryApi } from '@reduxjs/toolkit/dist/query/baseQueryTypes';
import { RootState } from 'store';
import { FetchError } from 'types';

const baseQuery = fetchBaseQuery({
const defaultBaseQuery = fetchBaseQuery({
baseUrl: 'https://www.googleapis.com/youtube/v3/',
prepareHeaders: (headers, { getState }) => {
const apiKey = (getState() as RootState).settings.apiKey;
Expand All @@ -12,6 +18,24 @@ const baseQuery = fetchBaseQuery({
},
});

const baseQuery = (
args: string | FetchArgs,
api: BaseQueryApi,
extraOptions: { timeout?: number } = {}
) =>
Promise.race([
defaultBaseQuery(args, api, extraOptions),
new Promise((resolve) =>
setTimeout(
() =>
resolve({
error: { status: 'FETCH_ERROR', error: FetchError.TIMEOUT },
}),
extraOptions.timeout ?? 10000
)
) as ReturnType<typeof defaultBaseQuery>,
]);

export const youtubeApi = createApi({
reducerPath: 'youtubeApi',
baseQuery,
Expand Down
20 changes: 19 additions & 1 deletion src/store/services/youtube/endpoints.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { FetchBaseQueryError } from '@reduxjs/toolkit/dist/query';
import { niceDuration, shortenLargeNumber, TimeAgo } from 'helpers/utils';
import { Channel, ChannelActivities, Response, Video, VideoFlags } from 'types';
import { saveVideos } from 'store/reducers/videos';
import { parseVideoField, evaluateField } from './utils';
import { parseVideoField, evaluateField, isFetchTimeoutError } from './utils';

type FindChannelByNameArgs = {
name: string;
Expand Down Expand Up @@ -156,6 +156,15 @@ const extendedApi = youtubeApi.injectEndpoints({
})
);
if (!result.data) {
if (isFetchTimeoutError(result.error)) {
console.error(result.error);
return {
data: {
items: [],
total: 0,
},
};
}
return { error: result.error as FetchBaseQueryError };
}
return {
Expand All @@ -180,6 +189,15 @@ const extendedApi = youtubeApi.injectEndpoints({
})
);
if (activities.error) {
if (isFetchTimeoutError(activities.error)) {
console.error(activities.error);
return {
data: {
items: [],
total: 0,
},
};
}
return { error: activities.error as FetchBaseQueryError };
}
const { items, total } = queries.getChannelActivities.transformResponse(
Expand Down
6 changes: 5 additions & 1 deletion src/store/services/youtube/utils.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import { Video, ChannelFilterOperator } from 'types';
import { FetchBaseQueryError } from '@reduxjs/toolkit/dist/query';
import { Video, ChannelFilterOperator, FetchError } from 'types';

export const isFetchTimeoutError = (err: FetchBaseQueryError | undefined) =>
err && err.status === 'FETCH_ERROR' && err.error === FetchError.TIMEOUT;

export const parseVideoField = (video: Video, field: string) => {
const parsed = video[field as keyof Video];
Expand Down
4 changes: 4 additions & 0 deletions src/types/api.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
export enum FetchError {
TIMEOUT = 'timed out',
}

export interface Response {
kind?: string;
etag?: string;
Expand Down

0 comments on commit c6dddc6

Please sign in to comment.