diff --git a/allstarr/Controllers/AdminController.cs b/allstarr/Controllers/AdminController.cs index a1a788b..0c450d6 100644 --- a/allstarr/Controllers/AdminController.cs +++ b/allstarr/Controllers/AdminController.cs @@ -28,6 +28,7 @@ public class AdminController : ControllerBase private readonly SpotifyApiSettings _spotifyApiSettings; private readonly SpotifyImportSettings _spotifyImportSettings; private readonly JellyfinSettings _jellyfinSettings; + private readonly SubsonicSettings _subsonicSettings; private readonly DeezerSettings _deezerSettings; private readonly QobuzSettings _qobuzSettings; private readonly SquidWTFSettings _squidWtfSettings; @@ -52,6 +53,7 @@ public class AdminController : ControllerBase IOptions spotifyApiSettings, IOptions spotifyImportSettings, IOptions jellyfinSettings, + IOptions subsonicSettings, IOptions deezerSettings, IOptions qobuzSettings, IOptions squidWtfSettings, @@ -69,6 +71,7 @@ public class AdminController : ControllerBase _spotifyApiSettings = spotifyApiSettings.Value; _spotifyImportSettings = spotifyImportSettings.Value; _jellyfinSettings = jellyfinSettings.Value; + _subsonicSettings = subsonicSettings.Value; _deezerSettings = deezerSettings.Value; _qobuzSettings = qobuzSettings.Value; _squidWtfSettings = squidWtfSettings.Value; @@ -1408,8 +1411,13 @@ public class AdminController : ControllerBase }, library = new { - downloadPath = _configuration["Library:DownloadPath"] ?? "./downloads", - keptPath = _configuration["Library:KeptPath"] ?? "/app/kept" + downloadPath = _subsonicSettings.StorageMode == StorageMode.Cache + ? Path.Combine("cache", "Music") + : (_configuration["Library:DownloadPath"] ?? "./downloads"), + keptPath = _configuration["Library:KeptPath"] ?? "/app/kept", + storageMode = _subsonicSettings.StorageMode.ToString(), + cacheDurationHours = _subsonicSettings.CacheDurationHours, + downloadMode = _subsonicSettings.DownloadMode.ToString() }, deezer = new { diff --git a/allstarr/Services/Common/CacheCleanupService.cs b/allstarr/Services/Common/CacheCleanupService.cs index e62e71a..662e1a0 100644 --- a/allstarr/Services/Common/CacheCleanupService.cs +++ b/allstarr/Services/Common/CacheCleanupService.cs @@ -94,16 +94,16 @@ public class CacheCleanupService : BackgroundService { var fileInfo = new FileInfo(filePath); - // Use last access time to determine if file should be deleted - // This gets updated when a cached file is streamed - if (fileInfo.LastAccessTimeUtc < cutoffTime) + // Use last write time (when file was created/downloaded) to determine if file should be deleted + // LastAccessTime is unreliable on many filesystems (noatime mount option) + if (fileInfo.LastWriteTimeUtc < cutoffTime) { var size = fileInfo.Length; File.Delete(filePath); deletedCount++; totalSize += size; - _logger.LogDebug("Deleted cached file: {Path} (last accessed: {LastAccess})", - filePath, fileInfo.LastAccessTimeUtc); + _logger.LogDebug("Deleted cached file: {Path} (age: {Age:F1} hours)", + filePath, (DateTime.UtcNow - fileInfo.LastWriteTimeUtc).TotalHours); } } catch (Exception ex) diff --git a/allstarr/Services/SquidWTF/SquidWTFDownloadService.cs b/allstarr/Services/SquidWTF/SquidWTFDownloadService.cs index 1cdc3a4..e6a7c14 100644 --- a/allstarr/Services/SquidWTF/SquidWTFDownloadService.cs +++ b/allstarr/Services/SquidWTF/SquidWTFDownloadService.cs @@ -135,10 +135,10 @@ public class SquidWTFDownloadService : BaseDownloadService // Resolve unique path if file already exists outputPath = PathHelper.ResolveUniquePath(outputPath); - // Race all endpoints to download from the fastest one - Logger.LogInformation("🏁 Racing {Count} endpoints for fastest download", _fallbackHelper.EndpointCount); + // Use round-robin with fallback for downloads to reduce CPU usage + Logger.LogDebug("Using round-robin endpoint selection for download"); - var response = await _fallbackHelper.RaceAllEndpointsAsync(async (baseUrl, ct) => + var response = await _fallbackHelper.TryWithFallbackAsync(async (baseUrl) => { // Map quality settings to Tidal's quality levels per hifi-api spec var quality = _squidwtfSettings.Quality?.ToUpperInvariant() switch @@ -154,10 +154,10 @@ public class SquidWTFDownloadService : BaseDownloadService var url = $"{baseUrl}/track/?id={trackId}&quality={quality}"; // Get download info from this endpoint - var infoResponse = await _httpClient.GetAsync(url, ct); + var infoResponse = await _httpClient.GetAsync(url, cancellationToken); infoResponse.EnsureSuccessStatusCode(); - var json = await infoResponse.Content.ReadAsStringAsync(ct); + var json = await infoResponse.Content.ReadAsStringAsync(cancellationToken); var doc = JsonDocument.Parse(json); if (!doc.RootElement.TryGetProperty("data", out var data)) @@ -185,8 +185,8 @@ public class SquidWTFDownloadService : BaseDownloadService request.Headers.Add("User-Agent", "Mozilla/5.0"); request.Headers.Add("Accept", "*/*"); - return await _httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, ct); - }, cancellationToken); + return await _httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, cancellationToken); + }); response.EnsureSuccessStatusCode(); @@ -228,8 +228,8 @@ public class SquidWTFDownloadService : BaseDownloadService { return await QueueRequestAsync(async () => { - // Race all endpoints for fastest download info retrieval - return await _fallbackHelper.RaceAllEndpointsAsync(async (baseUrl, ct) => + // Use round-robin with fallback instead of racing to reduce CPU usage + return await _fallbackHelper.TryWithFallbackAsync(async (baseUrl) => { // Map quality settings to Tidal's quality levels per hifi-api spec var quality = _squidwtfSettings.Quality?.ToUpperInvariant() switch @@ -246,10 +246,10 @@ public class SquidWTFDownloadService : BaseDownloadService Logger.LogDebug("Fetching track download info from: {Url}", url); - var response = await _httpClient.GetAsync(url, ct); + var response = await _httpClient.GetAsync(url, cancellationToken); response.EnsureSuccessStatusCode(); - var json = await response.Content.ReadAsStringAsync(ct); + var json = await response.Content.ReadAsStringAsync(cancellationToken); var doc = JsonDocument.Parse(json); if (!doc.RootElement.TryGetProperty("data", out var data)) @@ -282,8 +282,7 @@ public class SquidWTFDownloadService : BaseDownloadService ? audioQualityEl.GetString() : "LOSSLESS"; - Logger.LogDebug("Decoded manifest - URL: {Url}, MIME: {MimeType}, Quality: {Quality}", - downloadUrl, mimeType, audioQuality); + Logger.LogInformation("Track download URL obtained from hifi-api: {Url}", downloadUrl); return new DownloadResult { @@ -291,7 +290,7 @@ public class SquidWTFDownloadService : BaseDownloadService MimeType = mimeType ?? "audio/flac", AudioQuality = audioQuality ?? "LOSSLESS" }; - }, cancellationToken); + }); }); }