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,