mirror of
https://github.com/SoPat712/allstarr.git
synced 2026-02-09 23:55:10 -05:00
Fix memory leak in ActiveDownloads dictionary
- Changed ActiveDownloads from Dictionary to ConcurrentDictionary for thread safety - Added automatic cleanup of completed downloads after 5 minutes - Added automatic cleanup of failed downloads after 2 minutes - This fixes the 929MB -> 10MB memory issue where downloads were never removed from tracking
This commit is contained in:
@@ -5,6 +5,7 @@ using allstarr.Models.Search;
|
|||||||
using allstarr.Models.Subsonic;
|
using allstarr.Models.Subsonic;
|
||||||
using allstarr.Services.Local;
|
using allstarr.Services.Local;
|
||||||
using allstarr.Services.Subsonic;
|
using allstarr.Services.Subsonic;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
using TagLib;
|
using TagLib;
|
||||||
using IOFile = System.IO.File;
|
using IOFile = System.IO.File;
|
||||||
|
|
||||||
@@ -27,7 +28,7 @@ public abstract class BaseDownloadService : IDownloadService
|
|||||||
protected readonly string DownloadPath;
|
protected readonly string DownloadPath;
|
||||||
protected readonly string CachePath;
|
protected readonly string CachePath;
|
||||||
|
|
||||||
protected readonly Dictionary<string, DownloadInfo> ActiveDownloads = new();
|
protected readonly ConcurrentDictionary<string, DownloadInfo> ActiveDownloads = new();
|
||||||
protected readonly SemaphoreSlim DownloadLock = new(1, 1);
|
protected readonly SemaphoreSlim DownloadLock = new(1, 1);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -298,6 +299,14 @@ public abstract class BaseDownloadService : IDownloadService
|
|||||||
|
|
||||||
song.LocalPath = localPath;
|
song.LocalPath = localPath;
|
||||||
|
|
||||||
|
// Clean up completed download from tracking after a short delay
|
||||||
|
_ = Task.Run(async () =>
|
||||||
|
{
|
||||||
|
await Task.Delay(TimeSpan.FromMinutes(5)); // Keep for 5 minutes for status checks
|
||||||
|
ActiveDownloads.TryRemove(songId, out _);
|
||||||
|
Logger.LogDebug("Cleaned up completed download tracking for {SongId}", songId);
|
||||||
|
});
|
||||||
|
|
||||||
// Register BEFORE releasing lock to prevent race conditions (both cache and download modes)
|
// Register BEFORE releasing lock to prevent race conditions (both cache and download modes)
|
||||||
await LocalLibraryService.RegisterDownloadedSongAsync(song, localPath);
|
await LocalLibraryService.RegisterDownloadedSongAsync(song, localPath);
|
||||||
|
|
||||||
@@ -360,6 +369,14 @@ public abstract class BaseDownloadService : IDownloadService
|
|||||||
{
|
{
|
||||||
downloadInfo.Status = DownloadStatus.Failed;
|
downloadInfo.Status = DownloadStatus.Failed;
|
||||||
downloadInfo.ErrorMessage = ex.Message;
|
downloadInfo.ErrorMessage = ex.Message;
|
||||||
|
|
||||||
|
// Clean up failed download from tracking after a short delay
|
||||||
|
_ = Task.Run(async () =>
|
||||||
|
{
|
||||||
|
await Task.Delay(TimeSpan.FromMinutes(2)); // Keep for 2 minutes for error reporting
|
||||||
|
ActiveDownloads.TryRemove(songId, out _);
|
||||||
|
Logger.LogDebug("Cleaned up failed download tracking for {SongId}", songId);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
Logger.LogError(ex, "Download failed for {SongId}", songId);
|
Logger.LogError(ex, "Download failed for {SongId}", songId);
|
||||||
throw;
|
throw;
|
||||||
|
|||||||
Reference in New Issue
Block a user