feat: 5-tier search index with library + similar artist expansion

Rewrite SearchIndex with tiered background build:

Tier 1 — Sitewide instant (<5s, 12 calls): top artists, recordings,
  and release groups across 4 time ranges. Searchable immediately.

Tier 2 — Sitewide full discog (~16min, 2881 calls): top 20 RGs +
  top 100 recordings per sitewide artist (~1440 unique artists from
  all_time/this_year/this_month/this_week union).

Tier 3 — Library artists (~4min, 664 calls): match local library
  artist names against known MBIDs, index their full discographies.
  Catches the user's personal taste that sitewide misses.

Tier 4 — Similar artists (~24min, ~4300 calls): fetch similar
  artists from LB labs for each library artist, index their
  discographies. Fans out into the user's taste neighborhood.

Tier 5 — Organic growth (0 calls): BrowseReleaseGroups now writes
  to the search index in a background goroutine. Every artist page
  view adds that artist's discography to the index for free.

Other changes:
- indexRGsPerArtist bumped 10→20 (96% vs 88% coverage)
- indexRecsPerArtist bumped 10→100 (track-name searchability)
- indexMinPopularity = 50 (cuts noise from long tails)
- Dedicated 3 req/s rate limiter for indexer
- Labs similar-artists endpoint at labs.api.listenbrainz.org
- Each tier marks index as ready on completion so search improves
  progressively during the ~44min total build
This commit is contained in:
2026-03-25 12:49:20 -04:00
parent cf40909313
commit 48acede1bc
2 changed files with 695 additions and 166 deletions
+19 -1
View File
@@ -93,8 +93,26 @@ func (e *Service) LookupReleaseGroup(mbid string) (*MBReleaseGroup, error) {
// ---------------------------------------------------------------------------
// BrowseReleaseGroups fetches release groups for a given artist MBID.
// Also adds results to the search index (Tier 5: organic growth).
func (e *Service) BrowseReleaseGroups(artistMBID string) ([]MBReleaseGroup, error) {
return e.mb.BrowseReleaseGroups(e.ctx, artistMBID)
rgs, err := e.mb.BrowseReleaseGroups(e.ctx, artistMBID)
if err != nil {
return nil, err
}
// Tier 5: organic growth — index this discography.
// Look up the artist name from the first result's credit, or
// fall back to the MBID.
artistName := artistMBID
artist, lookupErr := e.mb.LookupArtist(e.ctx, artistMBID)
if lookupErr == nil && artist != nil {
artistName = artist.Name
}
go e.index.AddFromCache(artistName, artistMBID, rgs)
return rgs, nil
}
// BrowseReleases fetches releases for a given release group MBID.
File diff suppressed because it is too large Load Diff