From 51648438242d4550f620f2a457bb641eafcf7a1e Mon Sep 17 00:00:00 2001 From: nk Date: Wed, 3 Jun 2026 20:51:28 +0300 Subject: [PATCH] =?UTF-8?q?perf(enrich):=20rate-limiter=20=D0=BD=D0=B0=20D?= =?UTF-8?q?iscogs=20+=20concurrency=205=20(=D0=BE=D0=B1=D0=BB=D0=BE=D0=B6?= =?UTF-8?q?=D0=BA=D0=B8=20=D0=B1=D1=8B=D1=81=D1=82=D1=80=D0=B5=D0=B5)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Discogs ограничен ≥1.1с между вызовами (≤54/мин, без 429) независимо от параллельности. Параллельность 5 → обложки (iTunes, без лимита) и скачивание льются быстрее. Решает медленное наполнение обложек живого набора. Co-Authored-By: Claude Opus 4.8 --- src/enrich/discogs.service.ts | 14 ++++++++++++++ src/enrich/enrichment.service.ts | 6 ++++-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/enrich/discogs.service.ts b/src/enrich/discogs.service.ts index 1a60b0e..5b97de9 100644 --- a/src/enrich/discogs.service.ts +++ b/src/enrich/discogs.service.ts @@ -33,13 +33,27 @@ export class DiscogsService { private readonly token = process.env.DISCOGS_TOKEN ?? ''; private readonly userAgent = 'radiOLA/1.0 +https://radiola.app'; + // Глобальный rate-limiter: Discogs ~60 запросов/мин. Разносим вызовы ≥1.1с + // независимо от параллельности обогащения (иначе 429). + private nextSlot = 0; + private readonly minIntervalMs = 1100; + // Без токена обогащение жанрами не работает (поиск требует авторизации) get enabled(): boolean { return this.token.length > 0; } + private async rateLimit(): Promise { + const now = Date.now(); + const start = Math.max(now, this.nextSlot); + this.nextSlot = start + this.minIntervalMs; + const wait = start - now; + if (wait > 0) await new Promise((r) => setTimeout(r, wait)); + } + async lookup(artist: string, song: string): Promise { if (!this.enabled) return null; + await this.rateLimit(); const params = new URLSearchParams({ artist, diff --git a/src/enrich/enrichment.service.ts b/src/enrich/enrichment.service.ts index fb11e44..4e31154 100644 --- a/src/enrich/enrichment.service.ts +++ b/src/enrich/enrichment.service.ts @@ -17,8 +17,10 @@ export class EnrichmentService { // Очередь обогащения с троттлингом (под лимиты Discogs/iTunes) private readonly queue: string[] = []; private running = false; - private readonly throttleMs = 1200; - private readonly concurrency = 2; + // Discogs сам себя лимитирует (rate-limiter в DiscogsService), поэтому можно + // выше параллельность: обложки (iTunes, без лимита) льются быстрее. + private readonly throttleMs = 300; + private readonly concurrency = 5; constructor( private readonly prisma: PrismaService,