prematch on startup

This commit is contained in:
2026-02-02 12:31:09 -05:00
parent 82b480c47e
commit 4111b5228d
3 changed files with 79 additions and 20 deletions

View File

@@ -3096,6 +3096,54 @@ public class JellyfinController : ControllerBase
return Ok(results);
}
/// <summary>
/// Manually trigger track matching for all Spotify playlists.
/// GET /spotify/match?api_key=YOUR_KEY
/// </summary>
[HttpGet("spotify/match", Order = 1)]
[ServiceFilter(typeof(ApiKeyAuthFilter))]
public async Task<IActionResult> TriggerSpotifyMatch([FromServices] IEnumerable<IHostedService> hostedServices)
{
if (!_spotifySettings.Enabled)
{
return BadRequest(new { error = "Spotify Import is not enabled" });
}
_logger.LogInformation("Manual Spotify track matching triggered");
// Find the SpotifyTrackMatchingService
var matchingService = hostedServices
.OfType<allstarr.Services.Spotify.SpotifyTrackMatchingService>()
.FirstOrDefault();
if (matchingService == null)
{
return StatusCode(500, new { error = "SpotifyTrackMatchingService not found" });
}
// Trigger matching asynchronously
_ = Task.Run(async () =>
{
try
{
await matchingService.TriggerMatchingAsync();
}
catch (Exception ex)
{
_logger.LogError(ex, "Error during manual track matching");
}
});
return Ok(new
{
status = "started",
message = "Track matching started in background. Check logs for progress.",
playlists = _spotifySettings.PlaylistNames.Count > 0
? _spotifySettings.PlaylistNames
: _spotifySettings.PlaylistIds
});
}
private List<allstarr.Models.Spotify.MissingTrack> ParseMissingTracksJson(string json)
{
var tracks = new List<allstarr.Models.Spotify.MissingTrack>();

View File

@@ -72,28 +72,19 @@ public class SpotifyMissingTracksFetcher : BackgroundService
}
_logger.LogInformation("========================================");
// Run once on startup if we haven't run in the last 24 hours
// Always run once on startup to ensure we have missing tracks
if (!_hasRunOnce)
{
var shouldRunOnStartup = await ShouldRunOnStartupAsync();
if (shouldRunOnStartup)
_logger.LogInformation("Running initial fetch on startup");
try
{
_logger.LogInformation("Running initial fetch on startup (bypassing sync window check)");
try
{
await FetchMissingTracksAsync(stoppingToken, bypassSyncWindowCheck: true);
_hasRunOnce = true;
}
catch (Exception ex)
{
_logger.LogError(ex, "Error during startup fetch");
}
}
else
{
_logger.LogInformation("Skipping startup fetch - already have recent cache");
await FetchMissingTracksAsync(stoppingToken, bypassSyncWindowCheck: true);
_hasRunOnce = true;
}
catch (Exception ex)
{
_logger.LogError(ex, "Error during startup fetch");
}
}
while (!stoppingToken.IsCancellationRequested)

View File

@@ -44,6 +44,17 @@ public class SpotifyTrackMatchingService : BackgroundService
// Wait a bit for the fetcher to run first
await Task.Delay(TimeSpan.FromMinutes(2), stoppingToken);
// Run once on startup to match any existing missing tracks
try
{
_logger.LogInformation("Running initial track matching on startup");
await MatchAllPlaylistsAsync(stoppingToken);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error during startup track matching");
}
while (!stoppingToken.IsCancellationRequested)
{
try
@@ -60,6 +71,15 @@ public class SpotifyTrackMatchingService : BackgroundService
}
}
/// <summary>
/// Public method to trigger matching manually (called from controller).
/// </summary>
public async Task TriggerMatchingAsync()
{
_logger.LogInformation("Manual track matching triggered");
await MatchAllPlaylistsAsync(CancellationToken.None);
}
private async Task MatchAllPlaylistsAsync(CancellationToken cancellationToken)
{
_logger.LogInformation("=== STARTING TRACK MATCHING ===");
@@ -103,7 +123,7 @@ public class SpotifyTrackMatchingService : BackgroundService
var existingMatched = await _cache.GetAsync<List<Song>>(matchedTracksKey);
if (existingMatched != null && existingMatched.Count > 0)
{
_logger.LogDebug("Playlist {Playlist} already has {Count} matched tracks cached, skipping",
_logger.LogInformation("Playlist {Playlist} already has {Count} matched tracks cached, skipping",
playlistName, existingMatched.Count);
return;
}
@@ -112,7 +132,7 @@ public class SpotifyTrackMatchingService : BackgroundService
var missingTracks = await _cache.GetAsync<List<MissingTrack>>(missingTracksKey);
if (missingTracks == null || missingTracks.Count == 0)
{
_logger.LogDebug("No missing tracks found for {Playlist}, skipping matching", playlistName);
_logger.LogInformation("No missing tracks found for {Playlist}, skipping matching", playlistName);
return;
}
@@ -158,7 +178,7 @@ public class SpotifyTrackMatchingService : BackgroundService
if (matchCount % 10 == 0)
{
_logger.LogDebug("Matched {Count}/{Total} tracks for {Playlist}",
_logger.LogInformation("Matched {Count}/{Total} tracks for {Playlist}",
matchCount, missingTracks.Count, playlistName);
}
}