feat(enrich): крон — гарантировать обложку играющим сейчас трекам

Раз в минуту проходим now_playing: создаём Track при отсутствии (без записи
проигрывания) и приоритетно обогащаем тех, у кого нет обложки. Now-playing-обложки
(DFM и др.) появляются быстро у всех станций, не дожидаясь смены трека/бэкафилла.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
nk
2026-06-03 14:39:13 +03:00
parent 916fc301e4
commit bb74d631c1

View File

@@ -57,6 +57,38 @@ export class EnrichmentService {
for (const t of pending) this.enqueue(t.id);
}
// Раз в минуту гарантируем обложку у играющих СЕЙЧАС треков: создаём Track
// при отсутствии (без записи проигрывания) и приоритетно обогащаем тех, у кого
// ещё нет обложки. Так now-playing-обложки появляются быстро у всех сетей.
@Cron(CronExpression.EVERY_MINUTE)
async enrichNowPlaying(): Promise<void> {
const rows = await this.prisma.nowPlaying.findMany({
select: { artist: true, song: true },
});
for (const r of rows) {
const artist = (r.artist ?? '').trim();
const song = (r.song ?? '').trim();
if (!artist || !song) continue;
const normKey = this.buildNormKey(artist, song);
const track = await this.prisma.track.upsert({
where: { normKey },
create: { normKey, artist, song },
update: {},
select: { id: true, coverUrl: true },
});
if (!track.coverUrl) this.enqueue(track.id, { priority: true });
}
}
// Нормализованный ключ — как в ChartsService.recordPlay
private buildNormKey(artist: string, song: string): string {
return (
artist.toLowerCase().replace(/\s+/g, ' ') +
'|' +
song.toLowerCase().replace(/\s+/g, ' ')
);
}
private async drain(): Promise<void> {
if (this.running) return;
this.running = true;