Fix seasonal playlist track ID for non-spotify/itunes sources, fix polling interval leak
This commit is contained in:
parent
85ea2a810f
commit
d7e1cdeb83
4 changed files with 40 additions and 5 deletions
|
|
@ -371,8 +371,10 @@ class SeasonalDiscoveryService:
|
||||||
config = SEASONAL_CONFIG[season_key]
|
config = SEASONAL_CONFIG[season_key]
|
||||||
keywords = config['keywords']
|
keywords = config['keywords']
|
||||||
|
|
||||||
# Use the right track ID column based on source
|
# itunes stores IDs in itunes_track_id; all other sources
|
||||||
track_id_col = 'spotify_track_id' if source == 'spotify' else 'itunes_track_id'
|
# (spotify, deezer, discogs, hydrabase, etc.) use spotify_track_id
|
||||||
|
# as the generic ID column.
|
||||||
|
track_id_col = 'itunes_track_id' if source == 'itunes' else 'spotify_track_id'
|
||||||
|
|
||||||
seasonal_tracks = []
|
seasonal_tracks = []
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -44348,7 +44348,10 @@ def get_current_seasonal_playlist():
|
||||||
if not track_ids:
|
if not track_ids:
|
||||||
return jsonify({"success": True, "tracks": []})
|
return jsonify({"success": True, "tracks": []})
|
||||||
|
|
||||||
track_id_col = 'spotify_track_id' if active_source == 'spotify' else 'itunes_track_id'
|
# itunes stores IDs in itunes_track_id; all other sources
|
||||||
|
# (spotify, deezer, discogs, hydrabase, etc.) use spotify_track_id
|
||||||
|
# as the generic ID column.
|
||||||
|
track_id_col = 'itunes_track_id' if active_source == 'itunes' else 'spotify_track_id'
|
||||||
tracks = []
|
tracks = []
|
||||||
with database._get_connection() as conn:
|
with database._get_connection() as conn:
|
||||||
cursor = conn.cursor()
|
cursor = conn.cursor()
|
||||||
|
|
@ -44477,8 +44480,10 @@ def get_seasonal_playlist(season_key):
|
||||||
if not track_ids:
|
if not track_ids:
|
||||||
return jsonify({"success": True, "tracks": []})
|
return jsonify({"success": True, "tracks": []})
|
||||||
|
|
||||||
# Use source-appropriate ID column for lookups
|
# itunes stores IDs in itunes_track_id; all other sources
|
||||||
track_id_col = 'spotify_track_id' if active_source == 'spotify' else 'itunes_track_id'
|
# (spotify, deezer, discogs, hydrabase, etc.) use spotify_track_id
|
||||||
|
# as the generic ID column.
|
||||||
|
track_id_col = 'itunes_track_id' if active_source == 'itunes' else 'spotify_track_id'
|
||||||
|
|
||||||
# Fetch track details from seasonal tracks or discovery pool (filtered by source)
|
# Fetch track details from seasonal tracks or discovery pool (filtered by source)
|
||||||
tracks = []
|
tracks = []
|
||||||
|
|
|
||||||
|
|
@ -9332,7 +9332,23 @@ function pollDiscoverSyncFromTab(playlistType, virtualPlaylistId, playlistName)
|
||||||
}
|
}
|
||||||
|
|
||||||
function pollDiscoverBatchFromTab(playlistType, batchId, playlistName) {
|
function pollDiscoverBatchFromTab(playlistType, batchId, playlistName) {
|
||||||
|
// Clear any existing poller for this playlist type
|
||||||
|
if (discoverSyncPollers[playlistType]) {
|
||||||
|
clearInterval(discoverSyncPollers[playlistType]);
|
||||||
|
delete discoverSyncPollers[playlistType];
|
||||||
|
}
|
||||||
|
|
||||||
|
let ticks = 0;
|
||||||
|
const maxTicks = 600; // 30 min at 3s intervals
|
||||||
|
|
||||||
const pollInterval = setInterval(async () => {
|
const pollInterval = setInterval(async () => {
|
||||||
|
ticks++;
|
||||||
|
// Stall guard — stop polling after maxTicks or if the card is no longer in DOM
|
||||||
|
if (ticks > maxTicks || !document.getElementById(`discover-sync-card-${playlistType}`)) {
|
||||||
|
clearInterval(pollInterval);
|
||||||
|
delete discoverSyncPollers[playlistType];
|
||||||
|
return;
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
const resp = await fetch(`/api/playlists/${batchId}/download_status`);
|
const resp = await fetch(`/api/playlists/${batchId}/download_status`);
|
||||||
if (!resp.ok) { clearInterval(pollInterval); return; }
|
if (!resp.ok) { clearInterval(pollInterval); return; }
|
||||||
|
|
@ -9341,6 +9357,7 @@ function pollDiscoverBatchFromTab(playlistType, batchId, playlistName) {
|
||||||
|
|
||||||
if (phase === 'complete' || phase === 'error' || phase === 'cancelled') {
|
if (phase === 'complete' || phase === 'error' || phase === 'cancelled') {
|
||||||
clearInterval(pollInterval);
|
clearInterval(pollInterval);
|
||||||
|
delete discoverSyncPollers[playlistType];
|
||||||
const btn = document.getElementById(`discover-sync-btn-${playlistType}`);
|
const btn = document.getElementById(`discover-sync-btn-${playlistType}`);
|
||||||
if (btn) { btn.disabled = false; btn.textContent = '\u27f3 Sync Now'; }
|
if (btn) { btn.disabled = false; btn.textContent = '\u27f3 Sync Now'; }
|
||||||
|
|
||||||
|
|
@ -9387,8 +9404,12 @@ function pollDiscoverBatchFromTab(playlistType, batchId, playlistName) {
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
clearInterval(pollInterval);
|
clearInterval(pollInterval);
|
||||||
|
delete discoverSyncPollers[playlistType];
|
||||||
}
|
}
|
||||||
}, 3000);
|
}, 3000);
|
||||||
|
|
||||||
|
// Register so page-leave cleanup can clear it
|
||||||
|
discoverSyncPollers[playlistType] = pollInterval;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -2243,6 +2243,13 @@ async function loadPageData(pageId) {
|
||||||
if (typeof _stopNebulaLivePolling === 'function') _stopNebulaLivePolling();
|
if (typeof _stopNebulaLivePolling === 'function') _stopNebulaLivePolling();
|
||||||
if (pageId !== 'sync') {
|
if (pageId !== 'sync') {
|
||||||
cleanupBeatportContent();
|
cleanupBeatportContent();
|
||||||
|
// Clear any discover sync tab pollers when leaving the sync page
|
||||||
|
if (typeof discoverSyncPollers === 'object') {
|
||||||
|
for (const key of Object.keys(discoverSyncPollers)) {
|
||||||
|
clearInterval(discoverSyncPollers[key]);
|
||||||
|
delete discoverSyncPollers[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
switch (pageId) {
|
switch (pageId) {
|
||||||
case 'dashboard':
|
case 'dashboard':
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue