sync window for spotify playlists

This commit is contained in:
2026-02-02 18:24:49 -05:00
parent 1bb902d96a
commit 04079223c2

View File

@@ -80,10 +80,11 @@ public class SpotifyMissingTracksFetcher : BackgroundService
var syncEndTime = syncTime.AddHours(settings.SyncWindowHours);
_logger.LogInformation("Search Schedule:");
_logger.LogInformation(" Plugin sync time: {Time:HH:mm} (configured)", syncTime);
_logger.LogInformation(" Search window: {Start:HH:mm} - {End:HH:mm} ({Hours}h window)",
_logger.LogInformation(" Plugin sync time: {Time:HH:mm} UTC (configured)", syncTime);
_logger.LogInformation(" Search window: {Start:HH:mm} - {End:HH:mm} UTC ({Hours}h window)",
syncTime, syncEndTime, settings.SyncWindowHours);
_logger.LogInformation(" Will search for missing tracks files every 5 minutes during window");
_logger.LogInformation(" Will search for new files once per day after sync window ends");
_logger.LogInformation(" Background check interval: 5 minutes");
// Fetch playlist names from Jellyfin
await LoadPlaylistNamesAsync();
@@ -114,7 +115,7 @@ public class SpotifyMissingTracksFetcher : BackgroundService
}
else
{
_logger.LogInformation("Skipping startup fetch - existing cache is still current");
_logger.LogInformation("Skipping startup fetch - already have current files");
_hasRunOnce = true;
}
}
@@ -123,7 +124,13 @@ public class SpotifyMissingTracksFetcher : BackgroundService
{
try
{
await FetchMissingTracksAsync(stoppingToken);
// Only fetch if we're past today's sync window AND we haven't fetched today yet
var shouldFetch = await ShouldFetchNowAsync();
if (shouldFetch)
{
await FetchMissingTracksAsync(stoppingToken);
_hasRunOnce = true;
}
}
catch (Exception ex)
{
@@ -134,6 +141,47 @@ public class SpotifyMissingTracksFetcher : BackgroundService
}
}
private async Task<bool> ShouldFetchNowAsync()
{
var settings = _spotifySettings.Value;
var now = DateTime.UtcNow;
// Calculate today's sync window
var todaySync = now.Date
.AddHours(settings.SyncStartHour)
.AddMinutes(settings.SyncStartMinute);
var todaySyncEnd = todaySync.AddHours(settings.SyncWindowHours);
// Only fetch if we're past today's sync window
if (now < todaySyncEnd)
{
return false;
}
// Check if we already have today's files
foreach (var playlistName in _playlistIdToName.Values)
{
var filePath = GetCacheFilePath(playlistName);
if (File.Exists(filePath))
{
var fileTime = File.GetLastWriteTimeUtc(filePath);
// If file is from today's sync or later, we already have it
if (fileTime >= todaySync)
{
continue;
}
}
// Missing today's file for this playlist
return true;
}
// All playlists have today's files
return false;
}
private async Task LoadPlaylistNamesAsync()
{
_playlistIdToName.Clear();
@@ -157,19 +205,22 @@ public class SpotifyMissingTracksFetcher : BackgroundService
var settings = _spotifySettings.Value;
var now = DateTime.UtcNow;
// Calculate when today's sync window ends
// Calculate today's sync window
var todaySync = now.Date
.AddHours(settings.SyncStartHour)
.AddMinutes(settings.SyncStartMinute);
var todaySyncEnd = todaySync.AddHours(settings.SyncWindowHours);
// If we haven't reached today's sync window end yet, check if we have yesterday's file
_logger.LogInformation("Today's sync window: {Start:yyyy-MM-dd HH:mm} - {End:yyyy-MM-dd HH:mm} UTC",
todaySync, todaySyncEnd);
_logger.LogInformation("Current time: {Now:yyyy-MM-dd HH:mm} UTC", now);
// If we're still before today's sync window end, we should have yesterday's or today's file
// Don't search again until after today's sync window ends
if (now < todaySyncEnd)
{
_logger.LogInformation("Today's sync window hasn't ended yet (ends at {End})", todaySyncEnd);
_logger.LogInformation("Checking if we have a recent cache file...");
_logger.LogInformation("We're before today's sync window end - checking if we have recent cache...");
// Check if we have any cache (file or Redis) for all playlists
var allPlaylistsHaveCache = true;
foreach (var playlistName in _playlistIdToName.Values)
@@ -206,13 +257,65 @@ public class SpotifyMissingTracksFetcher : BackgroundService
if (allPlaylistsHaveCache)
{
_logger.LogInformation("=== ALL PLAYLISTS HAVE CACHE - SKIPPING STARTUP FETCH ===");
_logger.LogInformation("Will search again after {Time:yyyy-MM-dd HH:mm} UTC", todaySyncEnd);
return false;
}
}
else
// If we're after today's sync window end, check if we already have today's file
if (now >= todaySyncEnd)
{
_logger.LogInformation("Today's sync window has passed (ended at {End})", todaySyncEnd);
_logger.LogInformation("Will search for new files");
_logger.LogInformation("We're after today's sync window end - checking if we already fetched today's files...");
var allPlaylistsHaveTodaysFile = true;
foreach (var playlistName in _playlistIdToName.Values)
{
var filePath = GetCacheFilePath(playlistName);
var cacheKey = $"spotify:missing:{playlistName}";
// Check if file exists and was created today (after sync start)
if (File.Exists(filePath))
{
var fileTime = File.GetLastWriteTimeUtc(filePath);
// File should be from today's sync window or later
if (fileTime >= todaySync)
{
var fileAge = DateTime.UtcNow - fileTime;
_logger.LogInformation(" {Playlist}: Have today's file (created {Time:yyyy-MM-dd HH:mm}, age: {Age:F1}h)",
playlistName, fileTime, fileAge.TotalHours);
// Load into Redis if not already there
if (!await _cache.ExistsAsync(cacheKey))
{
await LoadFromFileCache(playlistName);
}
continue;
}
else
{
_logger.LogInformation(" {Playlist}: File is old (from {Time:yyyy-MM-dd HH:mm}, before today's sync)",
playlistName, fileTime);
}
}
else
{
_logger.LogInformation(" {Playlist}: No file found", playlistName);
}
allPlaylistsHaveTodaysFile = false;
}
if (allPlaylistsHaveTodaysFile)
{
_logger.LogInformation("=== ALL PLAYLISTS HAVE TODAY'S FILES - SKIPPING STARTUP FETCH ===");
// Calculate when to search next (tomorrow after sync window)
var tomorrowSyncEnd = todaySyncEnd.AddDays(1);
_logger.LogInformation("Will search again after {Time:yyyy-MM-dd HH:mm} UTC", tomorrowSyncEnd);
return false;
}
}
_logger.LogInformation("=== WILL FETCH ON STARTUP ===");