From b99a199ef3d1e496dbfed561e10508b2969369ff Mon Sep 17 00:00:00 2001 From: Josh Patra Date: Fri, 6 Feb 2026 23:48:18 -0500 Subject: [PATCH] Fix lyrics fetching and disable prefetching - Fix LyricsPrefetchService to use server API key for Jellyfin lyrics checks - Remove Spotify lyrics caching (local Docker container is fast) - Disable lyrics prefetching service (not needed - Jellyfin/Spotify are fast) - Add POST /api/admin/cache/clear-lyrics endpoint to clear LRCLIB cache - Only LRCLIB lyrics are cached now (external API) --- allstarr/Controllers/AdminController.cs | 24 +++++++++++++++++++ allstarr/Program.cs | 5 ++-- .../Services/Lyrics/LyricsPrefetchService.cs | 10 ++++---- .../Services/Lyrics/SpotifyLyricsService.cs | 12 +--------- 4 files changed, 33 insertions(+), 18 deletions(-) diff --git a/allstarr/Controllers/AdminController.cs b/allstarr/Controllers/AdminController.cs index da6ecd7..84a262a 100644 --- a/allstarr/Controllers/AdminController.cs +++ b/allstarr/Controllers/AdminController.cs @@ -1738,6 +1738,30 @@ public class AdminController : ControllerBase }); } + /// + /// Clear all cached lyrics (LRCLIB only - Jellyfin and Spotify lyrics are not cached) + /// + [HttpPost("cache/clear-lyrics")] + public async Task ClearLyricsCache() + { + _logger.LogInformation("Lyrics cache clear requested from admin UI"); + + var clearedRedisKeys = 0; + + // Clear all lyrics cache keys (pattern-based deletion) + // This includes LRCLIB lyrics and manual mappings + var lyricsKeysDeleted = await _cache.DeleteByPatternAsync("lyrics:*"); + clearedRedisKeys += lyricsKeysDeleted; + + _logger.LogInformation("Lyrics cache cleared: {RedisKeys} Redis keys deleted", clearedRedisKeys); + + return Ok(new { + message = "Lyrics cache cleared successfully", + redisKeysDeleted = clearedRedisKeys, + note = "Only LRCLIB lyrics are cached. Jellyfin and Spotify lyrics are fetched on-demand (fast)." + }); + } + /// /// Restart the allstarr container to apply configuration changes /// diff --git a/allstarr/Program.cs b/allstarr/Program.cs index 60e17b6..e6b1490 100644 --- a/allstarr/Program.cs +++ b/allstarr/Program.cs @@ -568,8 +568,9 @@ builder.Services.AddSingleton sp.GetRequiredService()); // Register lyrics prefetch service (prefetches lyrics for all playlist tracks) -builder.Services.AddSingleton(); -builder.Services.AddHostedService(sp => sp.GetRequiredService()); +// DISABLED - No need to prefetch since Jellyfin and Spotify lyrics are fast +// builder.Services.AddSingleton(); +// builder.Services.AddHostedService(sp => sp.GetRequiredService()); // Register MusicBrainz service for metadata enrichment builder.Services.Configure(options => diff --git a/allstarr/Services/Lyrics/LyricsPrefetchService.cs b/allstarr/Services/Lyrics/LyricsPrefetchService.cs index 43a0617..dd05c09 100644 --- a/allstarr/Services/Lyrics/LyricsPrefetchService.cs +++ b/allstarr/Services/Lyrics/LyricsPrefetchService.cs @@ -406,9 +406,9 @@ public class LyricsPrefetchService : BackgroundService } // Directly check if this track has lyrics using the item ID - var (lyricsResult, lyricsStatusCode) = await proxyService.GetJsonAsync( + // Use internal method with server API key since this is a background operation + var (lyricsResult, lyricsStatusCode) = await proxyService.GetJsonAsyncInternal( $"Audio/{jellyfinItemId}/Lyrics", - null, null); if (lyricsResult != null && lyricsStatusCode == 200) @@ -455,7 +455,7 @@ public class LyricsPrefetchService : BackgroundService ["limit"] = "5" // Get a few results to find best match }; - var (searchResult, statusCode) = await proxyService.GetJsonAsync("Items", searchParams, null); + var (searchResult, statusCode) = await proxyService.GetJsonAsyncInternal("Items", searchParams); if (searchResult == null || statusCode != 200) { @@ -511,9 +511,9 @@ public class LyricsPrefetchService : BackgroundService } // Check if this track has lyrics - var (lyricsResult, lyricsStatusCode) = await proxyService.GetJsonAsync( + // Use internal method with server API key since this is a background operation + var (lyricsResult, lyricsStatusCode) = await proxyService.GetJsonAsyncInternal( $"Audio/{bestMatchId}/Lyrics", - null, null); if (lyricsResult != null && lyricsStatusCode == 200) diff --git a/allstarr/Services/Lyrics/SpotifyLyricsService.cs b/allstarr/Services/Lyrics/SpotifyLyricsService.cs index 4cd54a1..c47278b 100644 --- a/allstarr/Services/Lyrics/SpotifyLyricsService.cs +++ b/allstarr/Services/Lyrics/SpotifyLyricsService.cs @@ -63,15 +63,7 @@ public class SpotifyLyricsService // Normalize track ID (remove URI prefix if present) spotifyTrackId = ExtractTrackId(spotifyTrackId); - // Check cache - var cacheKey = $"spotify:lyrics:{spotifyTrackId}"; - var cached = await _cache.GetAsync(cacheKey); - if (cached != null) - { - _logger.LogDebug("Returning cached Spotify lyrics for track {TrackId}", spotifyTrackId); - return cached; - } - + // NO CACHING - Spotify lyrics come from local Docker container (fast) try { var url = $"{_settings.LyricsApiUrl}/?trackid={spotifyTrackId}&format=id3"; @@ -92,8 +84,6 @@ public class SpotifyLyricsService if (result != null) { - // Cache for 30 days (lyrics don't change) - await _cache.SetAsync(cacheKey, result, TimeSpan.FromDays(30)); _logger.LogInformation("Got Spotify lyrics from sidecar for track {TrackId} ({LineCount} lines)", spotifyTrackId, result.Lines.Count); }