fix(auth,download): playlists/likes 401, suppression downloads, 429 formats
CI / build-and-test (push) Failing after 8m20s
CI / build-and-test (push) Failing after 8m20s
- likes + playlists: authMiddlewareCookieAware (cookies + Bearer) au lieu du Bearer seul -> corrige 401 Unauthorized meme connecte (creation playlist, ajout video, bouton J'aime) - add-to-playlist/like-button/search-box: retire HttpClientModule local qui court-circuitait les intercepteurs fonctionnels - intercepteur: refresh+retry sur 401 meme sans token en memoire (F5) - UserService: apiBase() au lieu de /proxy/api en dur (prod :4000) - J'aime: envoie titre/miniature, erreur visible au lieu de bouton mort - download: seaux separes (lectures 120/min, ecritures 30/min, formats 30/min) + reponses limiter en JSON rate_limited + Retry-After - formats: cache memoire 10 min + ytdlpNetOpts + retry front avec backoff - polling allege (downloads 5s, suivi job 4s, 429 transitoire non fatal) - erreurs FR precises (http-error.util): 401/403/404/410/429/quota/500 avec compte a rebours + bouton Reessayer
This commit is contained in:
@@ -3,6 +3,7 @@ import { CommonModule } from '@angular/common';
|
||||
import { RouterLink } from '@angular/router';
|
||||
import { DownloadService, type DownloadJob, type DownloadQuota } from '../../../services/download.service';
|
||||
import { AuthService } from '../../../services/auth.service';
|
||||
import { frenchDownloadError } from '../../../utils/http-error.util';
|
||||
import { TranslatePipe } from '../../../pipes/translate.pipe';
|
||||
import { ProviderBadgeComponent } from '../../../app/shared/components/provider-badge/provider-badge.component';
|
||||
|
||||
@@ -88,14 +89,15 @@ export class DownloadsComponent {
|
||||
retry(job: DownloadJob): void {
|
||||
if (this.busyIds().has(job.id)) return;
|
||||
this.markBusy(job.id, true);
|
||||
this.error.set(null);
|
||||
this.downloads.retryJob(job.id).subscribe({
|
||||
next: () => {
|
||||
this.markBusy(job.id, false);
|
||||
this.reload();
|
||||
},
|
||||
error: () => {
|
||||
error: (err) => {
|
||||
this.markBusy(job.id, false);
|
||||
this.error.set('Nouvel essai impossible pour le moment.');
|
||||
this.error.set(frenchDownloadError(err));
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -103,14 +105,16 @@ export class DownloadsComponent {
|
||||
cancel(job: DownloadJob): void {
|
||||
if (this.busyIds().has(job.id)) return;
|
||||
this.markBusy(job.id, true);
|
||||
this.error.set(null);
|
||||
this.downloads.cancelJob(job.id).subscribe({
|
||||
next: () => {
|
||||
this.markBusy(job.id, false);
|
||||
this.items.update((list) => list.filter((j) => j.id !== job.id));
|
||||
this.syncPoller();
|
||||
},
|
||||
error: () => {
|
||||
error: (err) => {
|
||||
this.markBusy(job.id, false);
|
||||
this.error.set('Suppression impossible pour le moment.');
|
||||
this.error.set(frenchDownloadError(err));
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -188,7 +192,9 @@ export class DownloadsComponent {
|
||||
private syncPoller(): void {
|
||||
const hasActive = this.items().some((j) => ACTIVE_STATES.has(j.state));
|
||||
if (hasActive && !this.poller) {
|
||||
this.poller = setInterval(() => this.refreshActive(), 3000);
|
||||
// 5 s : le polling agressif (3 s) saturait à lui seul le seau
|
||||
// anti-abus et affamait suppressions + formats (429).
|
||||
this.poller = setInterval(() => this.refreshActive(), 5000);
|
||||
} else if (!hasActive && this.poller) {
|
||||
clearInterval(this.poller);
|
||||
this.poller = null;
|
||||
|
||||
Reference in New Issue
Block a user