@@ -4,12 +4,12 @@ import { computed, reactive, watch } from 'vue';
4
4
5
5
import type { BaseCacheOption } from '@dvcol/base-http-client' ;
6
6
import type {
7
+ TraktCollectionProgress ,
7
8
TraktEpisodeExtended ,
8
9
TraktEpisodeShort ,
9
- TraktCollectionProgress ,
10
- TraktWatchedProgress ,
11
10
TraktSeasonExtended ,
12
11
TraktShowExtended ,
12
+ TraktWatchedProgress ,
13
13
} from '@dvcol/trakt-http-client/models' ;
14
14
15
15
import { type ShowProgress , ShowProgressType } from '~/models/list-scroll.model' ;
@@ -32,6 +32,26 @@ type LoadingDictionary = Record<string, boolean>;
32
32
type SeasonEpisodesLoadingDictionary = Record < string , Record < number , boolean > > ;
33
33
type EpisodeLoadingDictionary = Record < string , Record < number , Record < number , boolean > > > ;
34
34
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
+
35
55
const watchProgressToListProgress = ( progress : TraktWatchedProgress | TraktCollectionProgress , id : string | number ) : ShowProgress => {
36
56
let completed = 0 ;
37
57
let aired = 0 ;
@@ -81,12 +101,22 @@ export const useShowStore = defineStore('data.show', () => {
81
101
const showWatchedProgressLoading = reactive < LoadingDictionary > ( { } ) ;
82
102
const showCollectionProgressLoading = reactive < LoadingDictionary > ( { } ) ;
83
103
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
+
84
111
const clearProgressState = ( ) => {
85
112
clearProxy ( showsWatchedProgress ) ;
86
113
clearProxy ( showsCollectionProgress ) ;
87
114
88
115
clearProxy ( showWatchedProgressLoading ) ;
89
116
clearProxy ( showCollectionProgressLoading ) ;
117
+
118
+ clearProxy ( showWatchedProgressError ) ;
119
+ clearProxy ( showCollectionProgressError ) ;
90
120
} ;
91
121
92
122
const clearState = ( ) => {
@@ -99,6 +129,12 @@ export const useShowStore = defineStore('data.show', () => {
99
129
clearProxy ( showsSeasonsLoading ) ;
100
130
clearProxy ( showsSeasonEpisodesLoading ) ;
101
131
clearProxy ( showsEpisodesLoading ) ;
132
+
133
+ clearProxy ( showsError ) ;
134
+ clearProxy ( showsSeasonsError ) ;
135
+ clearProxy ( showsSeasonEpisodesError ) ;
136
+ clearProxy ( showsEpisodesError ) ;
137
+
102
138
clearProgressState ( ) ;
103
139
} ;
104
140
@@ -113,9 +149,11 @@ export const useShowStore = defineStore('data.show', () => {
113
149
showsLoading [ id ] = true ;
114
150
try {
115
151
shows [ id ] = await TraktService . show . summary ( id ) ;
152
+ delete showsError [ id ] ;
116
153
} catch ( e ) {
117
154
logger . error ( 'Failed to fetch show' , id ) ;
118
155
NotificationService . error ( `Failed to fetch show '${ id } '.` , e ) ;
156
+ showsError [ id ] = { last : new Date ( ) , count : ( showsError [ id ] ?. count ?? 0 ) + 1 } ;
119
157
throw e ;
120
158
} finally {
121
159
showsLoading [ id ] = false ;
@@ -133,8 +171,10 @@ export const useShowStore = defineStore('data.show', () => {
133
171
showWatchedProgressLoading [ id ] = true ;
134
172
try {
135
173
showsWatchedProgress [ id ] = await TraktService . progress . show . watched ( id , cacheOption ) ;
174
+ delete showWatchedProgressError [ id ] ;
136
175
} catch ( e ) {
137
176
logger . error ( 'Failed to fetch show progress' , id ) ;
177
+ showWatchedProgressError [ id ] = { last : new Date ( ) , count : ( showWatchedProgressError [ id ] ?. count ?? 0 ) + 1 } ;
138
178
throw e ;
139
179
} finally {
140
180
showWatchedProgressLoading [ id ] = false ;
@@ -152,8 +192,10 @@ export const useShowStore = defineStore('data.show', () => {
152
192
showCollectionProgressLoading [ id ] = true ;
153
193
try {
154
194
showsCollectionProgress [ id ] = await TraktService . progress . show . collection ( id , cacheOption ) ;
195
+ delete showCollectionProgressError [ id ] ;
155
196
} catch ( e ) {
156
197
logger . error ( 'Failed to fetch show collection progress' , id ) ;
198
+ showCollectionProgressError [ id ] = { last : new Date ( ) , count : ( showCollectionProgressError [ id ] ?. count ?? 0 ) + 1 } ;
157
199
throw e ;
158
200
} finally {
159
201
showCollectionProgressLoading [ id ] = false ;
@@ -175,9 +217,11 @@ export const useShowStore = defineStore('data.show', () => {
175
217
acc [ season . number ] = season ;
176
218
return acc ;
177
219
} , { } ) ;
220
+ delete showsSeasonsError [ id ] ;
178
221
} catch ( e ) {
179
222
logger . error ( 'Failed to fetch show seasons' , id ) ;
180
223
NotificationService . error ( `Failed to fetch show seasons '${ id } '.` , e ) ;
224
+ showsSeasonsError [ id ] = { last : new Date ( ) , count : ( showsSeasonsError [ id ] ?. count ?? 0 ) + 1 } ;
181
225
throw e ;
182
226
} finally {
183
227
showsSeasonsLoading [ id ] = false ;
@@ -198,9 +242,14 @@ export const useShowStore = defineStore('data.show', () => {
198
242
const episodes = await TraktService . show . season ( id , season ) ;
199
243
if ( ! showsSeasonEpisodes [ id ] ) showsSeasonEpisodes [ id ] = { } ;
200
244
showsSeasonEpisodes [ id ] [ season ] = episodes ;
245
+ delete showsSeasonEpisodesError [ id ] ?. [ season ] ;
201
246
} catch ( e ) {
202
247
logger . error ( 'Failed to fetch show season episodes' , id , season ) ;
203
248
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
+ } ;
204
253
throw e ;
205
254
} finally {
206
255
showsSeasonEpisodesLoading [ id ] [ season ] = false ;
@@ -222,9 +271,17 @@ export const useShowStore = defineStore('data.show', () => {
222
271
if ( ! showsEpisodes [ id ] ) showsEpisodes [ id ] = { } ;
223
272
if ( ! showsEpisodes [ id ] [ season ] ) showsEpisodes [ id ] [ season ] = { } ;
224
273
showsEpisodes [ id ] [ season ] [ episode ] = await TraktService . show . episode ( { id, season, episode } ) ;
274
+ delete showsEpisodesError [ id ] ?. [ season ] ?. [ episode ] ;
225
275
} catch ( e ) {
226
276
logger . error ( 'Failed to fetch show episodes' , id , season , episode ) ;
227
277
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
+ } ;
228
285
throw e ;
229
286
} finally {
230
287
showsEpisodesLoading [ id ] [ season ] [ episode ] = false ;
@@ -262,7 +319,11 @@ export const useShowStore = defineStore('data.show', () => {
262
319
263
320
const getShowProgressLoading = ( id : number | string ) => computed ( ( ) => showWatchedProgressLoading [ id . toString ( ) ] ) ;
264
321
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
+ ) {
266
327
fetchShowProgress ( id . toString ( ) , cacheOptions ) . catch ( logger . error ) ;
267
328
}
268
329
return computed ( ( ) => {
@@ -274,8 +335,13 @@ export const useShowStore = defineStore('data.show', () => {
274
335
275
336
const getShowCollectionLoading = ( id : number | string ) => computed ( ( ) => showCollectionProgressLoading [ id . toString ( ) ] ) ;
276
337
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
+ ) {
278
343
fetchShowCollectionProgress ( id . toString ( ) ) . catch ( logger . error ) ;
344
+ }
279
345
return computed ( ( ) => {
280
346
const progress = showsCollectionProgress [ id . toString ( ) ] ;
281
347
if ( ! progress ) return undefined ;
0 commit comments