Skip to content

Commit 0a0e16e

Browse files
committed
feat(errors): adds error management to show store
1 parent 23f4173 commit 0a0e16e

File tree

1 file changed

+70
-4
lines changed

1 file changed

+70
-4
lines changed

src/stores/data/show.store.ts

+70-4
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@ import { computed, reactive, watch } from 'vue';
44

55
import type { BaseCacheOption } from '@dvcol/base-http-client';
66
import type {
7+
TraktCollectionProgress,
78
TraktEpisodeExtended,
89
TraktEpisodeShort,
9-
TraktCollectionProgress,
10-
TraktWatchedProgress,
1110
TraktSeasonExtended,
1211
TraktShowExtended,
12+
TraktWatchedProgress,
1313
} from '@dvcol/trakt-http-client/models';
1414

1515
import { type ShowProgress, ShowProgressType } from '~/models/list-scroll.model';
@@ -32,6 +32,26 @@ type LoadingDictionary = Record<string, boolean>;
3232
type SeasonEpisodesLoadingDictionary = Record<string, Record<number, boolean>>;
3333
type EpisodeLoadingDictionary = Record<string, Record<number, Record<number, boolean>>>;
3434

35+
type ErrorCount = { last: Date; count: number };
36+
type ErrorDictionary = Record<string, ErrorCount>;
37+
type SeasonEpisodesErrorDictionary = Record<string, Record<number, ErrorCount>>;
38+
type EpisodeErrorDictionary = Record<string, Record<number, Record<number, ErrorCount>>>;
39+
40+
const shouldRetry = (
41+
errorCount?: ErrorCount,
42+
{ retryCount = 2, retryTime = 10 * 1000, error }: { retryCount?: number; retryTime?: number; error?: unknown } = {},
43+
) => {
44+
if (!errorCount) return true;
45+
if (errorCount.count < retryCount || Date.now() > errorCount.last.getTime() + retryTime) return true;
46+
NotificationService.error(`Error threshold exceeded, throttling requests.`, {
47+
count: errorCount.count,
48+
threshold: retryCount,
49+
last: errorCount.last.toLocaleString(),
50+
error,
51+
});
52+
throw new Error('Error threshold exceeded, throttling requests.');
53+
};
54+
3555
const watchProgressToListProgress = (progress: TraktWatchedProgress | TraktCollectionProgress, id: string | number): ShowProgress => {
3656
let completed = 0;
3757
let aired = 0;
@@ -81,12 +101,22 @@ export const useShowStore = defineStore('data.show', () => {
81101
const showWatchedProgressLoading = reactive<LoadingDictionary>({});
82102
const showCollectionProgressLoading = reactive<LoadingDictionary>({});
83103

104+
const showsError = reactive<ErrorDictionary>({});
105+
const showsSeasonsError = reactive<ErrorDictionary>({});
106+
const showsSeasonEpisodesError = reactive<SeasonEpisodesErrorDictionary>({});
107+
const showsEpisodesError = reactive<EpisodeErrorDictionary>({});
108+
const showWatchedProgressError = reactive<ErrorDictionary>({});
109+
const showCollectionProgressError = reactive<ErrorDictionary>({});
110+
84111
const clearProgressState = () => {
85112
clearProxy(showsWatchedProgress);
86113
clearProxy(showsCollectionProgress);
87114

88115
clearProxy(showWatchedProgressLoading);
89116
clearProxy(showCollectionProgressLoading);
117+
118+
clearProxy(showWatchedProgressError);
119+
clearProxy(showCollectionProgressError);
90120
};
91121

92122
const clearState = () => {
@@ -99,6 +129,12 @@ export const useShowStore = defineStore('data.show', () => {
99129
clearProxy(showsSeasonsLoading);
100130
clearProxy(showsSeasonEpisodesLoading);
101131
clearProxy(showsEpisodesLoading);
132+
133+
clearProxy(showsError);
134+
clearProxy(showsSeasonsError);
135+
clearProxy(showsSeasonEpisodesError);
136+
clearProxy(showsEpisodesError);
137+
102138
clearProgressState();
103139
};
104140

@@ -113,9 +149,11 @@ export const useShowStore = defineStore('data.show', () => {
113149
showsLoading[id] = true;
114150
try {
115151
shows[id] = await TraktService.show.summary(id);
152+
delete showsError[id];
116153
} catch (e) {
117154
logger.error('Failed to fetch show', id);
118155
NotificationService.error(`Failed to fetch show '${id}'.`, e);
156+
showsError[id] = { last: new Date(), count: (showsError[id]?.count ?? 0) + 1 };
119157
throw e;
120158
} finally {
121159
showsLoading[id] = false;
@@ -133,8 +171,10 @@ export const useShowStore = defineStore('data.show', () => {
133171
showWatchedProgressLoading[id] = true;
134172
try {
135173
showsWatchedProgress[id] = await TraktService.progress.show.watched(id, cacheOption);
174+
delete showWatchedProgressError[id];
136175
} catch (e) {
137176
logger.error('Failed to fetch show progress', id);
177+
showWatchedProgressError[id] = { last: new Date(), count: (showWatchedProgressError[id]?.count ?? 0) + 1 };
138178
throw e;
139179
} finally {
140180
showWatchedProgressLoading[id] = false;
@@ -152,8 +192,10 @@ export const useShowStore = defineStore('data.show', () => {
152192
showCollectionProgressLoading[id] = true;
153193
try {
154194
showsCollectionProgress[id] = await TraktService.progress.show.collection(id, cacheOption);
195+
delete showCollectionProgressError[id];
155196
} catch (e) {
156197
logger.error('Failed to fetch show collection progress', id);
198+
showCollectionProgressError[id] = { last: new Date(), count: (showCollectionProgressError[id]?.count ?? 0) + 1 };
157199
throw e;
158200
} finally {
159201
showCollectionProgressLoading[id] = false;
@@ -175,9 +217,11 @@ export const useShowStore = defineStore('data.show', () => {
175217
acc[season.number] = season;
176218
return acc;
177219
}, {});
220+
delete showsSeasonsError[id];
178221
} catch (e) {
179222
logger.error('Failed to fetch show seasons', id);
180223
NotificationService.error(`Failed to fetch show seasons '${id}'.`, e);
224+
showsSeasonsError[id] = { last: new Date(), count: (showsSeasonsError[id]?.count ?? 0) + 1 };
181225
throw e;
182226
} finally {
183227
showsSeasonsLoading[id] = false;
@@ -198,9 +242,14 @@ export const useShowStore = defineStore('data.show', () => {
198242
const episodes = await TraktService.show.season(id, season);
199243
if (!showsSeasonEpisodes[id]) showsSeasonEpisodes[id] = {};
200244
showsSeasonEpisodes[id][season] = episodes;
245+
delete showsSeasonEpisodesError[id]?.[season];
201246
} catch (e) {
202247
logger.error('Failed to fetch show season episodes', id, season);
203248
NotificationService.error(`Failed to fetch show season episodes '${id}', season '${season}'.`, e);
249+
showsSeasonEpisodesError[id] = {
250+
...showsSeasonEpisodesError[id],
251+
[season]: { last: new Date(), count: (showsSeasonEpisodesError[id]?.[season]?.count ?? 0) + 1 },
252+
};
204253
throw e;
205254
} finally {
206255
showsSeasonEpisodesLoading[id][season] = false;
@@ -222,9 +271,17 @@ export const useShowStore = defineStore('data.show', () => {
222271
if (!showsEpisodes[id]) showsEpisodes[id] = {};
223272
if (!showsEpisodes[id][season]) showsEpisodes[id][season] = {};
224273
showsEpisodes[id][season][episode] = await TraktService.show.episode({ id, season, episode });
274+
delete showsEpisodesError[id]?.[season]?.[episode];
225275
} catch (e) {
226276
logger.error('Failed to fetch show episodes', id, season, episode);
227277
NotificationService.error(`Failed to fetch show episodes '${id}', season '${season}', episode '${episode}'.`, e);
278+
showsEpisodesError[id] = {
279+
...showsEpisodesError[id],
280+
[season]: {
281+
...showsEpisodesError[id]?.[season],
282+
[episode]: { last: new Date(), count: (showsEpisodesError[id]?.[season]?.[episode]?.count ?? 0) + 1 },
283+
},
284+
};
228285
throw e;
229286
} finally {
230287
showsEpisodesLoading[id][season][episode] = false;
@@ -262,7 +319,11 @@ export const useShowStore = defineStore('data.show', () => {
262319

263320
const getShowProgressLoading = (id: number | string) => computed(() => showWatchedProgressLoading[id.toString()]);
264321
const getShowWatchedProgress = (id: number | string, cacheOptions?: BaseCacheOption) => {
265-
if (!showsWatchedProgress[id.toString()] && !showWatchedProgressLoading[id.toString()]) {
322+
if (
323+
!showsWatchedProgress[id.toString()] &&
324+
!showWatchedProgressLoading[id.toString()] &&
325+
shouldRetry(showWatchedProgressError[id.toString()], { error: `Watched Progress for ${id.toString()}` })
326+
) {
266327
fetchShowProgress(id.toString(), cacheOptions).catch(logger.error);
267328
}
268329
return computed(() => {
@@ -274,8 +335,13 @@ export const useShowStore = defineStore('data.show', () => {
274335

275336
const getShowCollectionLoading = (id: number | string) => computed(() => showCollectionProgressLoading[id.toString()]);
276337
const getShowCollectionProgress = (id: number | string) => {
277-
if (!showsCollectionProgress[id.toString()] && !showCollectionProgressLoading[id.toString()])
338+
if (
339+
!showsCollectionProgress[id.toString()] &&
340+
!showCollectionProgressLoading[id.toString()] &&
341+
shouldRetry(showCollectionProgressError[id.toString()], { error: `Collection Progress for ${id.toString()}` })
342+
) {
278343
fetchShowCollectionProgress(id.toString()).catch(logger.error);
344+
}
279345
return computed(() => {
280346
const progress = showsCollectionProgress[id.toString()];
281347
if (!progress) return undefined;

0 commit comments

Comments
 (0)