Add configurable concurrent downloads setting
- New "Concurrent Downloads" dropdown on Settings page (1-10, default 3) - Saved to download_source.max_concurrent config key - All 6 batch creation sites use configured value instead of hardcoded 3 - Soulseek-only album downloads still use 1 worker (source reuse per user) - Hybrid/YouTube/Tidal/Qobuz/Deezer albums use full configured concurrency
This commit is contained in:
parent
b8870e7310
commit
9bcff9b43d
3 changed files with 42 additions and 5 deletions
|
|
@ -1896,6 +1896,23 @@ download_batches = {} # batch_id -> {queue, active_count, max_concurrent}
|
|||
tasks_lock = threading.Lock()
|
||||
batch_locks = {} # batch_id -> Lock() for atomic batch operations
|
||||
|
||||
def _get_max_concurrent():
|
||||
"""Get configured max concurrent downloads. Default 3."""
|
||||
return config_manager.get('download_source.max_concurrent', 3)
|
||||
|
||||
def _get_batch_max_concurrent(is_album=False, source=None):
|
||||
"""Get max concurrent workers for a batch.
|
||||
Soulseek album downloads always use 1 (source reuse per user).
|
||||
Everything else uses the configured setting."""
|
||||
if is_album and source in ('soulseek', None):
|
||||
# Check if active source is soulseek
|
||||
if source == 'soulseek':
|
||||
return 1
|
||||
mode = config_manager.get('download_source.mode', 'soulseek')
|
||||
if mode == 'soulseek':
|
||||
return 1
|
||||
return _get_max_concurrent()
|
||||
|
||||
# --- Session Download Statistics ---
|
||||
# Track individual download completions (matches dashboard.py behavior)
|
||||
session_completed_downloads = 0
|
||||
|
|
@ -21794,7 +21811,7 @@ def _process_wishlist_automatically(automation_id=None):
|
|||
'playlist_name': playlist_name,
|
||||
'queue': [],
|
||||
'active_count': 0,
|
||||
'max_concurrent': 1 if current_cycle == 'albums' else 3, # 1 worker for album source reuse, 3 for singles
|
||||
'max_concurrent': _get_batch_max_concurrent(is_album=(current_cycle == 'albums')),
|
||||
'queue_index': 0,
|
||||
'analysis_total': len(wishlist_tracks),
|
||||
'analysis_processed': 0,
|
||||
|
|
@ -22692,7 +22709,7 @@ def start_wishlist_missing_downloads():
|
|||
'playlist_name': playlist_name,
|
||||
'queue': task_queue,
|
||||
'active_count': 0,
|
||||
'max_concurrent': 1 if category == 'albums' else 3, # 1 worker for album source reuse, 3 for singles
|
||||
'max_concurrent': _get_batch_max_concurrent(is_album=(category == 'albums')),
|
||||
'queue_index': 0,
|
||||
'analysis_total': len(wishlist_tracks),
|
||||
'analysis_processed': 0,
|
||||
|
|
@ -27134,7 +27151,7 @@ def start_playlist_missing_downloads(playlist_id):
|
|||
download_batches[batch_id] = {
|
||||
'queue': [],
|
||||
'active_count': 0,
|
||||
'max_concurrent': 3,
|
||||
'max_concurrent': _get_max_concurrent(),
|
||||
'queue_index': 0,
|
||||
# Track state management (replicating sync.py)
|
||||
'permanently_failed_tracks': [],
|
||||
|
|
@ -29131,7 +29148,7 @@ def start_missing_tracks_process(playlist_id):
|
|||
'playlist_name': playlist_name,
|
||||
'queue': [],
|
||||
'active_count': 0,
|
||||
'max_concurrent': 1 if is_album_download else 3, # Album/EP: 1 worker for source reuse; Playlist: 3 workers
|
||||
'max_concurrent': _get_batch_max_concurrent(is_album=is_album_download),
|
||||
# Track state management (replicating sync.py)
|
||||
'permanently_failed_tracks': [],
|
||||
'cancelled_tracks': set(),
|
||||
|
|
@ -29229,7 +29246,7 @@ def start_missing_downloads():
|
|||
download_batches[batch_id] = {
|
||||
'queue': [],
|
||||
'active_count': 0,
|
||||
'max_concurrent': 3,
|
||||
'max_concurrent': _get_max_concurrent(),
|
||||
'queue_index': 0,
|
||||
# Track state management (replicating sync.py)
|
||||
'permanently_failed_tracks': [],
|
||||
|
|
|
|||
|
|
@ -4245,6 +4245,24 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Concurrent Downloads:</label>
|
||||
<select id="max-concurrent-downloads" class="form-select">
|
||||
<option value="1">1</option>
|
||||
<option value="2">2</option>
|
||||
<option value="3" selected>3 (Default)</option>
|
||||
<option value="4">4</option>
|
||||
<option value="5">5</option>
|
||||
<option value="6">6</option>
|
||||
<option value="8">8</option>
|
||||
<option value="10">10</option>
|
||||
</select>
|
||||
<div class="setting-help-text">
|
||||
Maximum simultaneous downloads per batch. Soulseek album downloads always use 1 worker
|
||||
due to per-user upload limits. Higher values speed up large playlists and wishlists.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Hybrid Mode Settings (shown only when hybrid is selected) -->
|
||||
<div id="hybrid-settings-container" style="display: none;">
|
||||
<div class="setting-help-text">
|
||||
|
|
|
|||
|
|
@ -5781,6 +5781,7 @@ async function loadSettingsData() {
|
|||
// Populate Download Source settings
|
||||
document.getElementById('download-source-mode').value = settings.download_source?.mode || 'soulseek';
|
||||
document.getElementById('stream-source').value = settings.download_source?.stream_source || 'youtube';
|
||||
document.getElementById('max-concurrent-downloads').value = settings.download_source?.max_concurrent || '3';
|
||||
loadHybridSourceOrder(settings);
|
||||
document.getElementById('tidal-download-quality').value = settings.tidal_download?.quality || 'lossless';
|
||||
document.getElementById('tidal-allow-fallback').checked = settings.tidal_download?.allow_fallback !== false;
|
||||
|
|
@ -6814,6 +6815,7 @@ async function saveSettings(quiet = false) {
|
|||
hybrid_secondary: document.getElementById('hybrid-secondary-source').value,
|
||||
hybrid_order: getHybridOrder(),
|
||||
stream_source: document.getElementById('stream-source').value,
|
||||
max_concurrent: parseInt(document.getElementById('max-concurrent-downloads').value) || 3,
|
||||
},
|
||||
tidal_download: {
|
||||
quality: document.getElementById('tidal-download-quality').value || 'lossless',
|
||||
|
|
|
|||
Loading…
Reference in a new issue