From a7bb8da1d5f030b4d1af7b784e768d0943dd191b Mon Sep 17 00:00:00 2001 From: destrodxbad Date: Tue, 18 Nov 2025 02:01:41 +0100 Subject: [PATCH 1/3] perf(websocket): Fix scope leak and add adaptive polling --- .../BackgroundServices/WebsocketsUpdater.cs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/server/RdtClient.Service/BackgroundServices/WebsocketsUpdater.cs b/server/RdtClient.Service/BackgroundServices/WebsocketsUpdater.cs index 10237d4..d466b8e 100644 --- a/server/RdtClient.Service/BackgroundServices/WebsocketsUpdater.cs +++ b/server/RdtClient.Service/BackgroundServices/WebsocketsUpdater.cs @@ -14,14 +14,15 @@ public class WebsocketsUpdater(ILogger logger, IServiceProvid await Task.Delay(1000, stoppingToken); } - var scope = serviceProvider.CreateScope(); - - var remoteService = scope.ServiceProvider.GetRequiredService(); + logger.LogInformation("WebsocketsUpdater started."); while (!stoppingToken.IsCancellationRequested) { try { + using var scope = serviceProvider.CreateScope(); + var remoteService = scope.ServiceProvider.GetRequiredService(); + await remoteService.Update(); } catch (Exception ex) @@ -29,7 +30,11 @@ public class WebsocketsUpdater(ILogger logger, IServiceProvid logger.LogError(ex, $"Unexpected error occurred in WebsocketsUpdater: {ex.Message}"); } - await Task.Delay(TimeSpan.FromSeconds(1), stoppingToken); + var delay = RdtHub.HasConnections + ? TimeSpan.FromSeconds(1) + : TimeSpan.FromSeconds(5); + + await Task.Delay(delay, stoppingToken); } logger.LogInformation("WebsocketsUpdater stopped."); From 47355030b5f241bd79ecadc983e9ba3837861f65 Mon Sep 17 00:00:00 2001 From: destrodxbad Date: Tue, 18 Nov 2025 02:03:13 +0100 Subject: [PATCH 2/3] perf(database): Configure SQLite with WAL mode and connection pooling --- server/RdtClient.Data/DiConfig.cs | 2 +- server/RdtClient.Service/BackgroundServices/Startup.cs | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/server/RdtClient.Data/DiConfig.cs b/server/RdtClient.Data/DiConfig.cs index 1a1b29e..636004d 100644 --- a/server/RdtClient.Data/DiConfig.cs +++ b/server/RdtClient.Data/DiConfig.cs @@ -14,7 +14,7 @@ public static class DiConfig throw new("Invalid database path found in appSettings"); } - var connectionString = $"Data Source={appSettings.Database.Path}"; + var connectionString = $"Data Source={appSettings.Database.Path};Cache=Shared;Pooling=True;Command Timeout=30"; services.AddDbContext(options => options.UseSqlite(connectionString)); services.AddScoped(); diff --git a/server/RdtClient.Service/BackgroundServices/Startup.cs b/server/RdtClient.Service/BackgroundServices/Startup.cs index d5c359a..551f30d 100644 --- a/server/RdtClient.Service/BackgroundServices/Startup.cs +++ b/server/RdtClient.Service/BackgroundServices/Startup.cs @@ -25,6 +25,12 @@ public class Startup(IServiceProvider serviceProvider) : IHostedService var dbContext = scope.ServiceProvider.GetRequiredService(); await dbContext.Database.MigrateAsync(cancellationToken); + // Configure SQLite for better concurrency and performance + await dbContext.Database.ExecuteSqlRawAsync("PRAGMA journal_mode=WAL;", cancellationToken); + await dbContext.Database.ExecuteSqlRawAsync("PRAGMA synchronous=NORMAL;", cancellationToken); + await dbContext.Database.ExecuteSqlRawAsync("PRAGMA busy_timeout=5000;", cancellationToken); + await dbContext.Database.ExecuteSqlRawAsync("PRAGMA cache_size=-64000;", cancellationToken); + var settings = scope.ServiceProvider.GetRequiredService(); await settings.Seed(); await settings.ResetCache(); From 15af54ed242402d5241aaa2d1afb94686291eb41 Mon Sep 17 00:00:00 2001 From: destrodxbad Date: Tue, 18 Nov 2025 02:04:51 +0100 Subject: [PATCH 3/3] perf(cache): Remove aggressive cache invalidation and optimize queries --- server/RdtClient.Data/Data/DownloadData.cs | 26 ---------------------- server/RdtClient.Data/Data/TorrentData.cs | 1 + 2 files changed, 1 insertion(+), 26 deletions(-) diff --git a/server/RdtClient.Data/Data/DownloadData.cs b/server/RdtClient.Data/Data/DownloadData.cs index 3b9e303..8e06bd9 100644 --- a/server/RdtClient.Data/Data/DownloadData.cs +++ b/server/RdtClient.Data/Data/DownloadData.cs @@ -47,8 +47,6 @@ public class DownloadData(DataContext dataContext) await dataContext.SaveChangesAsync(); - await TorrentData.VoidCache(); - return download; } @@ -65,8 +63,6 @@ public class DownloadData(DataContext dataContext) dbDownload.Link = unrestrictedLink; await dataContext.SaveChangesAsync(); - - await TorrentData.VoidCache(); } public async Task UpdateFileName(Guid downloadId, String fileName) @@ -82,8 +78,6 @@ public class DownloadData(DataContext dataContext) dbDownload.FileName = fileName; await dataContext.SaveChangesAsync(); - - await TorrentData.VoidCache(); } public async Task UpdateDownloadStarted(Guid downloadId, DateTimeOffset? dateTime) @@ -99,8 +93,6 @@ public class DownloadData(DataContext dataContext) dbDownload.DownloadStarted = dateTime; await dataContext.SaveChangesAsync(); - - await TorrentData.VoidCache(); } public async Task UpdateDownloadFinished(Guid downloadId, DateTimeOffset? dateTime) @@ -116,8 +108,6 @@ public class DownloadData(DataContext dataContext) dbDownload.DownloadFinished = dateTime; await dataContext.SaveChangesAsync(); - - await TorrentData.VoidCache(); } public async Task UpdateUnpackingQueued(Guid downloadId, DateTimeOffset? dateTime) @@ -133,8 +123,6 @@ public class DownloadData(DataContext dataContext) dbDownload.UnpackingQueued = dateTime; await dataContext.SaveChangesAsync(); - - await TorrentData.VoidCache(); } public async Task UpdateUnpackingStarted(Guid downloadId, DateTimeOffset? dateTime) @@ -150,8 +138,6 @@ public class DownloadData(DataContext dataContext) dbDownload.UnpackingStarted = dateTime; await dataContext.SaveChangesAsync(); - - await TorrentData.VoidCache(); } public async Task UpdateUnpackingFinished(Guid downloadId, DateTimeOffset? dateTime) @@ -167,8 +153,6 @@ public class DownloadData(DataContext dataContext) dbDownload.UnpackingFinished = dateTime; await dataContext.SaveChangesAsync(); - - await TorrentData.VoidCache(); } public async Task UpdateCompleted(Guid downloadId, DateTimeOffset? dateTime) @@ -184,8 +168,6 @@ public class DownloadData(DataContext dataContext) dbDownload.Completed = dateTime; await dataContext.SaveChangesAsync(); - - await TorrentData.VoidCache(); } public async Task UpdateError(Guid downloadId, String? error) @@ -201,8 +183,6 @@ public class DownloadData(DataContext dataContext) dbDownload.Error = error; await dataContext.SaveChangesAsync(); - - await TorrentData.VoidCache(); } public async Task UpdateRetryCount(Guid downloadId, Int32 retryCount) @@ -218,8 +198,6 @@ public class DownloadData(DataContext dataContext) dbDownload.RetryCount = retryCount; await dataContext.SaveChangesAsync(); - - await TorrentData.VoidCache(); } public async Task UpdateRemoteId(Guid downloadId, String remoteId) @@ -246,8 +224,6 @@ public class DownloadData(DataContext dataContext) dataContext.Downloads.RemoveRange(downloads); await dataContext.SaveChangesAsync(); - - await TorrentData.VoidCache(); } public async Task Reset(Guid downloadId) @@ -269,7 +245,5 @@ public class DownloadData(DataContext dataContext) dbDownload.Error = null; await dataContext.SaveChangesAsync(); - - await TorrentData.VoidCache(); } } \ No newline at end of file diff --git a/server/RdtClient.Data/Data/TorrentData.cs b/server/RdtClient.Data/Data/TorrentData.cs index e3484a1..b200ca2 100644 --- a/server/RdtClient.Data/Data/TorrentData.cs +++ b/server/RdtClient.Data/Data/TorrentData.cs @@ -18,6 +18,7 @@ public class TorrentData(DataContext dataContext) : ITorrentData { _torrentCache ??= await dataContext.Torrents .AsNoTracking() + .AsSplitQuery() .Include(m => m.Downloads) .ToListAsync();