- track_plays(played_at,track_id,station_id) покрывающий + tracks(first_seen_at) WHERE
pending частичный (применены CONCURRENTLY на проде + миграция idempotent)
- ChartsService.getTopTracks: in-memory TTL-кэш 90с по (period,genre,limit) → детальная
страница и параллельные запросы не пересчитывают тяжёлые агрегации
- NowPlayingService.ingest: не пишем now_playing и не шлём сокет, если трек не изменился
(было ~20k бесполезных upsert/час)
- enrichNowPlaying: вместо N+1 (300 upsert/мин) — один batched findMany по normKey
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>