mirror of
https://github.com/SoPat712/allstarr.git
synced 2026-02-09 23:55:10 -05:00
Release v1.0.0 - Production Ready
Major Features: - Spotify playlist injection with missing tracks search - Transparent proxy authentication system - WebSocket session management for external tracks - Manual track mapping and favorites system - Lyrics support (Spotify + LRCLib) with prefetching - Admin dashboard with analytics and configuration - Performance optimizations with health checks and endpoint racing - Comprehensive caching and memory management Performance Improvements: - Quick health checks (3s timeout) before trying endpoints - Health check results cached for 30 seconds - 5 minute timeout for large artist responses - Background Odesli conversion after streaming starts - Parallel lyrics prefetching - Endpoint benchmarking and racing - 16 SquidWTF endpoints with load balancing Reliability: - Automatic endpoint fallback and failover - Token expiration handling - Concurrent request optimization - Memory leak fixes - Proper session cleanup User Experience: - Web UI for configuration and playlist management - Real-time progress tracking - API analytics dashboard - Manual track mapping interface - Playlist statistics and health monitoring
This commit is contained in:
@@ -24,7 +24,6 @@ namespace allstarr.Services.Deezer;
|
||||
public class DeezerDownloadService : BaseDownloadService
|
||||
{
|
||||
private readonly HttpClient _httpClient;
|
||||
private readonly SemaphoreSlim _requestLock = new(1, 1);
|
||||
|
||||
private readonly string? _arl;
|
||||
private readonly string? _arlFallback;
|
||||
@@ -33,9 +32,6 @@ public class DeezerDownloadService : BaseDownloadService
|
||||
private string? _apiToken;
|
||||
private string? _licenseToken;
|
||||
|
||||
private DateTime _lastRequestTime = DateTime.MinValue;
|
||||
private readonly int _minRequestIntervalMs = 200;
|
||||
|
||||
private const string DeezerApiBase = "https://api.deezer.com";
|
||||
|
||||
// Deezer's standard Blowfish CBC encryption key for track decryption
|
||||
@@ -111,7 +107,10 @@ public class DeezerDownloadService : BaseDownloadService
|
||||
|
||||
// Build organized folder structure: Artist/Album/Track using AlbumArtist (fallback to Artist for singles)
|
||||
var artistForPath = song.AlbumArtist ?? song.Artist;
|
||||
var basePath = SubsonicSettings.StorageMode == StorageMode.Cache ? CachePath : DownloadPath;
|
||||
// Cache mode uses cache/Music folder (cleaned up after 24h), Permanent mode uses downloads folder
|
||||
var basePath = SubsonicSettings.StorageMode == StorageMode.Cache
|
||||
? Path.Combine("cache", "Music")
|
||||
: "downloads";
|
||||
var outputPath = PathHelper.BuildTrackPath(basePath, artistForPath, song.Album, song.Title, song.Track, extension);
|
||||
|
||||
// Create directories if they don't exist
|
||||
@@ -494,27 +493,6 @@ public class DeezerDownloadService : BaseDownloadService
|
||||
await RetryWithBackoffAsync<bool>(action, maxRetries, initialDelayMs);
|
||||
}
|
||||
|
||||
private async Task<T> QueueRequestAsync<T>(Func<Task<T>> action)
|
||||
{
|
||||
await _requestLock.WaitAsync();
|
||||
try
|
||||
{
|
||||
var now = DateTime.UtcNow;
|
||||
var timeSinceLastRequest = (now - _lastRequestTime).TotalMilliseconds;
|
||||
|
||||
if (timeSinceLastRequest < _minRequestIntervalMs)
|
||||
{
|
||||
await Task.Delay((int)(_minRequestIntervalMs - timeSinceLastRequest));
|
||||
}
|
||||
|
||||
_lastRequestTime = DateTime.UtcNow;
|
||||
return await action();
|
||||
}
|
||||
finally
|
||||
{
|
||||
_requestLock.Release();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
Reference in New Issue
Block a user