From 75f3b4f7045af8435d7cc35ecccfc61b2adcd5a7 Mon Sep 17 00:00:00 2001 From: Connor Johnstone Date: Sat, 21 Mar 2026 15:08:28 -0400 Subject: [PATCH] Sped up artist enrichment at least somewhat --- src/routes/artists.rs | 77 +++++++++++++++++++++++++++++-------------- 1 file changed, 53 insertions(+), 24 deletions(-) diff --git a/src/routes/artists.rs b/src/routes/artists.rs index dce7efa..7b0cabc 100644 --- a/src/routes/artists.rs +++ b/src/routes/artists.rs @@ -193,12 +193,29 @@ async fn get_cached_album_tracks( let release_mbid = if let Some(rid) = first_release_id { rid.to_string() } else { - // Browse releases for this release group (through shared rate limiter) - state - .mb_client - .resolve_release_from_group(rg_id) - .await - .map_err(|e| ApiError::Internal(format!("MB error for group {rg_id}: {e}")))? + // Check DB cache for previously resolved release MBID + let resolve_cache_key = format!("release_for_rg:{rg_id}"); + if let Ok(Some(cached_rid)) = queries::cache::get(state.db.conn(), &resolve_cache_key).await + { + cached_rid + } else { + // Browse releases for this release group (through shared rate limiter) + let rid = state + .mb_client + .resolve_release_from_group(rg_id) + .await + .map_err(|e| ApiError::Internal(format!("MB error for group {rg_id}: {e}")))?; + // Cache the resolved release MBID for 365 days — it never changes + let _ = queries::cache::set( + state.db.conn(), + &resolve_cache_key, + "musicbrainz", + &rid, + 365 * 86400, + ) + .await; + rid + } }; let mb_tracks = state @@ -259,7 +276,8 @@ pub async fn enrich_artist( quick_mode: bool, ) -> Result { // Resolve artist: local ID or MBID - let (artist, id, mbid) = if let Ok(local_id) = id_or_mbid.parse() { + // Track whether we already fetched artist info during resolution to avoid a duplicate API call + let (artist, id, mbid, prefetched_info) = if let Ok(local_id) = id_or_mbid.parse() { let artist = queries::artists::get_by_id(state.db.conn(), local_id).await?; let mbid = match &artist.musicbrainz_id { Some(m) => m.clone(), @@ -274,7 +292,7 @@ pub async fn enrich_artist( })? } }; - (artist, Some(local_id), mbid) + (artist, Some(local_id), mbid, None) } else { let mbid = id_or_mbid.to_string(); @@ -288,9 +306,10 @@ pub async fn enrich_artist( if let Some(a) = local { let local_id = a.id; - (a, Some(local_id), mbid) + (a, Some(local_id), mbid, None) } else { // Look up artist info from MusicBrainz by MBID — don't create a local record + // This fetches url-rels too, so we reuse it below instead of calling get_artist_info() again let info = state.mb_client.get_artist_info(&mbid).await.map_err(|e| { ApiError::NotFound(format!("artist MBID {mbid} not found: {e}")) @@ -307,24 +326,34 @@ pub async fn enrich_artist( monitored: false, last_checked_at: None, }; - (synthetic, None, mbid) + (synthetic, None, mbid, Some(info)) } }; - // Fetch detailed artist info (country, type, URLs) — best-effort - let artist_info = match state.mb_client.get_artist_info(&mbid).await { - Ok(info) => { - tracing::debug!( - mbid = %mbid, - urls = info.urls.len(), - country = ?info.country, - "fetched artist info" - ); - Some(info) - } - Err(e) => { - tracing::warn!(mbid = %mbid, error = %e, "failed to fetch artist info"); - None + // Fetch detailed artist info (country, type, URLs) — reuse if already fetched during resolution + let artist_info = if let Some(info) = prefetched_info { + tracing::debug!( + mbid = %mbid, + urls = info.urls.len(), + country = ?info.country, + "reusing prefetched artist info" + ); + Some(info) + } else { + match state.mb_client.get_artist_info(&mbid).await { + Ok(info) => { + tracing::debug!( + mbid = %mbid, + urls = info.urls.len(), + country = ?info.country, + "fetched artist info" + ); + Some(info) + } + Err(e) => { + tracing::warn!(mbid = %mbid, error = %e, "failed to fetch artist info"); + None + } } };