perf(backend): индексы, кэш чартов, пропуск upsert, фикс N+1 обогащения
- 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>
This commit is contained in:
@@ -139,6 +139,8 @@ model Track {
|
||||
likes TrackLike[]
|
||||
|
||||
@@index([genre])
|
||||
// Частичный индекс под бэкфилл обогащения создаётся миграцией (Prisma не умеет
|
||||
// partial WHERE): tracks_enrich_pending_idx (first_seen_at DESC) WHERE enrich_status='pending'.
|
||||
@@map("tracks")
|
||||
}
|
||||
|
||||
@@ -154,6 +156,8 @@ model TrackPlay {
|
||||
@@index([trackId, playedAt])
|
||||
@@index([playedAt])
|
||||
@@index([stationId])
|
||||
// Покрывающий индекс под агрегацию чартов (WHERE played_at>=X → GROUP BY track_id, COUNT DISTINCT station_id)
|
||||
@@index([playedAt, trackId, stationId], map: "track_plays_window_idx")
|
||||
@@map("track_plays")
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user