fix(twitch): token partagé + timeouts + fan-out réduit sur Home/Explore
CI / build-and-test (push) Successful in 14m10s
CI / build-and-test (push) Successful in 14m10s
This commit is contained in:
@@ -14,6 +14,7 @@ import { ChannelIdentityComponent } from '../../app/shared/components/channel-id
|
||||
import { InfiniteAnchorComponent } from '../shared/infinite-anchor/infinite-anchor.component';
|
||||
import { classifyVideo, isLiveVideo, isShortVideo } from '../../app/shared/utils/video-kind';
|
||||
import { map, of, switchMap, catchError, forkJoin, Observable } from 'rxjs';
|
||||
import { timeout } from 'rxjs/operators';
|
||||
import { PagedResult } from '../../services/youtube-api.service';
|
||||
|
||||
const TWITCH_THEME_KEYWORDS: Record<string, string[]> = {
|
||||
@@ -316,17 +317,27 @@ export class ProviderThemePageComponent implements OnDestroy {
|
||||
this.cdr.markForCheck();
|
||||
};
|
||||
|
||||
// Une section lente ne doit jamais bloquer les autres (forkJoin
|
||||
// échoue dès qu'un appel erreur : chaque section est bornée à 25 s
|
||||
// et retombe sur une page vide, le filet top-streams suit).
|
||||
const bounded = (call: Observable<PagedResult<Video>>): Observable<PagedResult<Video>> =>
|
||||
call.pipe(
|
||||
timeout(25000),
|
||||
catchError(() => of({ items: [], nextCursor: null } as PagedResult<Video>))
|
||||
);
|
||||
|
||||
const fetchAll = (gameId: string | null) => {
|
||||
const calls: Record<string, Observable<PagedResult<Video>>> = {};
|
||||
if (wantLive) {
|
||||
calls['live'] = gameId
|
||||
const liveCall = gameId
|
||||
? this.api.getTwitchGameStreamsPage(gameId, this.twitchCursors.live || undefined, 12).pipe(
|
||||
catchError(() => this.api.getTwitchTopStreamsPage(this.twitchCursors.live || undefined)))
|
||||
: this.api.getTwitchTopStreamsPage(this.twitchCursors.live || undefined);
|
||||
calls['live'] = bounded(liveCall);
|
||||
}
|
||||
if (wantVod) calls['vod'] = this.api.searchTwitchVodsPage(query, this.twitchCursors.vod || undefined);
|
||||
if (wantClip) calls['clip'] = this.api.searchTwitchClipsPage(query, this.twitchCursors.clip || undefined);
|
||||
if (wantChannel) calls['channel'] = this.api.searchTwitchAllChannelsPage(query, this.twitchCursors.channel || undefined, 20);
|
||||
if (wantVod) calls['vod'] = bounded(this.api.searchTwitchVodsPage(query, this.twitchCursors.vod || undefined));
|
||||
if (wantClip) calls['clip'] = bounded(this.api.searchTwitchClipsPage(query, this.twitchCursors.clip || undefined));
|
||||
if (wantChannel) calls['channel'] = bounded(this.api.searchTwitchAllChannelsPage(query, this.twitchCursors.channel || undefined, 20));
|
||||
if (Object.keys(calls).length === 0) {
|
||||
this.loading.set(false);
|
||||
this.loadingMore.set(false);
|
||||
@@ -359,8 +370,13 @@ export class ProviderThemePageComponent implements OnDestroy {
|
||||
};
|
||||
|
||||
if (firstPage) {
|
||||
// Première page : résoudre la catégorie Twitch pour des lives thématiques.
|
||||
this.api.searchTwitchCategory(query).subscribe({
|
||||
// Première page : résoudre la catégorie Twitch pour des lives
|
||||
// thématiques, SANS bloquer l'affichage (4 s max, la recherche de
|
||||
// catégorie séquentielle prenait plusieurs secondes à elle seule).
|
||||
this.api.searchTwitchCategory(query).pipe(
|
||||
timeout(4000),
|
||||
catchError(() => of(null))
|
||||
).subscribe({
|
||||
next: (game) => {
|
||||
if (snapshotVersion !== this.version) return;
|
||||
if (game) this.twitchGame.set(game);
|
||||
|
||||
Reference in New Issue
Block a user