Fixed issues with retrying and cancelling torrents.

This commit is contained in:
Roger Far 2021-10-28 08:29:42 -06:00
parent 799316413a
commit 0d5d28483b
8 changed files with 111 additions and 50 deletions

View file

@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [1.9.4] - 2021-10-28
### Changed
- Fixed issues retrying torrents after multiple failed downloads in large torrents.
## [1.9.3] - 2021-10-27 ## [1.9.3] - 2021-10-27
### Changed ### Changed
- Fixed issue with the unpack queue. - Fixed issue with the unpack queue.

View file

@ -55,7 +55,7 @@
<a class="navbar-item"> Profile </a> <a class="navbar-item"> Profile </a>
<a class="navbar-item" (click)="logout()"> Logout </a> <a class="navbar-item" (click)="logout()"> Logout </a>
<hr class="navbar-divider" /> <hr class="navbar-divider" />
<div class="navbar-item">Version 1.9.3</div> <div class="navbar-item">Version 1.9.4</div>
</div> </div>
</div> </div>
</div> </div>

View file

@ -1,6 +1,6 @@
{ {
"name": "rdt-client", "name": "rdt-client",
"version": "1.9.3", "version": "1.9.4",
"description": "This is a web interface to manage your torrents on Real-Debrid.", "description": "This is a web interface to manage your torrents on Real-Debrid.",
"main": "index.js", "main": "index.js",
"dependencies": { "dependencies": {

View file

@ -90,6 +90,9 @@ namespace RdtClient.Service.Services
public async Task Cancel() public async Task Cancel()
{ {
Finished = true;
Error = null;
if (Downloader == null) if (Downloader == null)
{ {
return; return;

View file

@ -168,6 +168,10 @@ namespace RdtClient.Service.Services.Downloaders
if (download == null) if (download == null)
{ {
DownloadComplete?.Invoke(this, new DownloadCompleteEventArgs
{
Error = $"Download was not found in Aria2"
});
return; return;
} }

View file

@ -4,9 +4,11 @@ using System.Diagnostics;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Net.Http; using System.Net.Http;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Web; using System.Web;
using Aria2NET; using Aria2NET;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Newtonsoft.Json; using Newtonsoft.Json;
using RdtClient.Data.Enums; using RdtClient.Data.Enums;
@ -27,15 +29,19 @@ namespace RdtClient.Service.Services
public static readonly ConcurrentDictionary<Guid, DownloadClient> ActiveDownloadClients = new(); public static readonly ConcurrentDictionary<Guid, DownloadClient> ActiveDownloadClients = new();
public static readonly ConcurrentDictionary<Guid, UnpackClient> ActiveUnpackClients = new(); public static readonly ConcurrentDictionary<Guid, UnpackClient> ActiveUnpackClients = new();
public static readonly SemaphoreSlim TorrentResetLock = new(1, 1);
private readonly ILogger<TorrentRunner> _logger; private readonly ILogger<TorrentRunner> _logger;
private readonly IServiceProvider _serviceProvider;
private readonly Torrents _torrents; private readonly Torrents _torrents;
private readonly Downloads _downloads; private readonly Downloads _downloads;
private readonly RemoteService _remoteService; private readonly RemoteService _remoteService;
private readonly HttpClient _httpClient; private readonly HttpClient _httpClient;
public TorrentRunner(ILogger<TorrentRunner> logger, Torrents torrents, Downloads downloads, RemoteService remoteService) public TorrentRunner(ILogger<TorrentRunner> logger, IServiceProvider serviceProvider, Torrents torrents, Downloads downloads, RemoteService remoteService)
{ {
_logger = logger; _logger = logger;
_serviceProvider = serviceProvider;
_torrents = torrents; _torrents = torrents;
_downloads = downloads; _downloads = downloads;
_remoteService = remoteService; _remoteService = remoteService;
@ -185,9 +191,17 @@ namespace RdtClient.Service.Services
{ {
Log($"Retrying torrent", download, download.Torrent); Log($"Retrying torrent", download, download.Torrent);
await _torrents.RetryTorrent(download.TorrentId, download.Torrent.RetryCount + 1); _ = Task.Run(async () =>
{
using var blockScope = _serviceProvider.CreateScope();
var torrentsService = (Torrents) blockScope.ServiceProvider.GetService(typeof(Torrents));
await torrentsService.RetryTorrent(download.TorrentId, download.Torrent.RetryCount + 1);
});
continue; // Force a delay and return the main loop to prevent concurrency issues.
await Task.Delay(10000);
return;
} }
else else
{ {
@ -468,8 +482,17 @@ namespace RdtClient.Service.Services
{ {
Log($"Retrying torrent", torrent); Log($"Retrying torrent", torrent);
await _torrents.RetryTorrent(torrent.TorrentId, torrent.RetryCount + 1); _ = Task.Run(async () =>
continue; {
using var blockScope = _serviceProvider.CreateScope();
var torrentsService = (Torrents) blockScope.ServiceProvider.GetService(typeof(Torrents));
await torrentsService.RetryTorrent(torrent.TorrentId, torrent.RetryCount + 1);
});
// Force a delay and return the main loop to prevent concurrency issues.
await Task.Delay(10000);
return;
} }
Log($"Received RealDebrid error: {torrent.RdStatusRaw}, not processing further", torrent); Log($"Received RealDebrid error: {torrent.RdStatusRaw}, not processing further", torrent);

View file

@ -27,6 +27,8 @@ namespace RdtClient.Service.Services
private readonly ITorrentClient _torrentClient; private readonly ITorrentClient _torrentClient;
public static readonly SemaphoreSlim TorrentResetLock = new(1, 1);
public Torrents(ILogger<Torrents> logger, public Torrents(ILogger<Torrents> logger,
TorrentData torrentData, TorrentData torrentData,
Downloads downloads, Downloads downloads,
@ -219,6 +221,8 @@ namespace RdtClient.Service.Services
Log($"Deleting", torrent); Log($"Deleting", torrent);
await UpdateComplete(torrentId, DateTimeOffset.UtcNow);
foreach (var download in torrent.Downloads) foreach (var download in torrent.Downloads)
{ {
while (TorrentRunner.ActiveDownloadClients.TryGetValue(download.DownloadId, out var downloadClient)) while (TorrentRunner.ActiveDownloadClients.TryGetValue(download.DownloadId, out var downloadClient))
@ -359,59 +363,82 @@ namespace RdtClient.Service.Services
public async Task RetryTorrent(Guid torrentId, Int32 retryCount) public async Task RetryTorrent(Guid torrentId, Int32 retryCount)
{ {
var torrent = await _torrentData.GetById(torrentId); await TorrentResetLock.WaitAsync();
if (torrent == null) try
{ {
return; var torrent = await _torrentData.GetById(torrentId);
}
Log($"Retrying Torrent", torrent); if (torrent == null)
foreach (var download in torrent.Downloads)
{
while (TorrentRunner.ActiveDownloadClients.TryGetValue(download.DownloadId, out var downloadClient))
{ {
await downloadClient.Cancel(); return;
await Task.Delay(100);
} }
while (TorrentRunner.ActiveUnpackClients.TryGetValue(download.DownloadId, out var unpackClient)) Log($"Retrying Torrent", torrent);
await UpdateComplete(torrent.TorrentId, DateTimeOffset.Now);
foreach (var download in torrent.Downloads)
{ {
unpackClient.Cancel(); await _downloads.UpdateError(download.DownloadId, null);
await _downloads.UpdateCompleted(download.DownloadId, DateTimeOffset.Now);
await Task.Delay(100);
} }
foreach (var download in torrent.Downloads)
{
while (TorrentRunner.ActiveDownloadClients.TryGetValue(download.DownloadId, out var downloadClient))
{
await downloadClient.Cancel();
await Task.Delay(100);
}
while (TorrentRunner.ActiveUnpackClients.TryGetValue(download.DownloadId, out var unpackClient))
{
unpackClient.Cancel();
await Task.Delay(100);
}
}
await Delete(torrentId, true, true, true);
if (String.IsNullOrWhiteSpace(torrent.FileOrMagnet))
{
throw new Exception($"Cannot re-add this torrent, original magnet or file not found");
}
Torrent newTorrent;
if (torrent.IsFile)
{
var bytes = Convert.FromBase64String(torrent.FileOrMagnet);
newTorrent = await UploadFile(bytes,
torrent.Category,
torrent.DownloadAction,
torrent.FinishedAction,
torrent.DownloadMinSize,
torrent.DownloadManualFiles,
torrent.Priority);
}
else
{
newTorrent = await UploadMagnet(torrent.FileOrMagnet,
torrent.Category,
torrent.DownloadAction,
torrent.FinishedAction,
torrent.DownloadMinSize,
torrent.DownloadManualFiles,
torrent.Priority);
}
await _torrentData.UpdateRetryCount(newTorrent.TorrentId, retryCount);
} }
finally
await Delete(torrentId, true, true, true);
if (String.IsNullOrWhiteSpace(torrent.FileOrMagnet))
{ {
throw new Exception($"Cannot re-add this torrent, original magnet or file not found"); TorrentResetLock.Release();
} }
Torrent newTorrent;
if (torrent.IsFile)
{
var bytes = Convert.FromBase64String(torrent.FileOrMagnet);
newTorrent = await UploadFile(bytes, torrent.Category, torrent.DownloadAction, torrent.FinishedAction, torrent.DownloadMinSize, torrent.DownloadManualFiles, torrent.Priority);
}
else
{
newTorrent = await UploadMagnet(torrent.FileOrMagnet,
torrent.Category,
torrent.DownloadAction,
torrent.FinishedAction,
torrent.DownloadMinSize,
torrent.DownloadManualFiles,
torrent.Priority);
}
await _torrentData.UpdateRetryCount(newTorrent.TorrentId, retryCount);
} }
public async Task RetryDownload(Guid downloadId) public async Task RetryDownload(Guid downloadId)

View file

@ -4,7 +4,7 @@
<TargetFramework>net5.0</TargetFramework> <TargetFramework>net5.0</TargetFramework>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<UserSecretsId>94c24cba-f03f-4453-a671-3640b517c573</UserSecretsId> <UserSecretsId>94c24cba-f03f-4453-a671-3640b517c573</UserSecretsId>
<Version>1.9.3</Version> <Version>1.9.4</Version>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>