Add simple retry mechanism for network connection drops.

This commit is contained in:
Roger Far 2021-01-13 11:04:42 -07:00
parent 860ffe95e4
commit 0a8793e4f9
6 changed files with 87 additions and 36 deletions

View file

@ -54,7 +54,10 @@ export class TorrentRowComponent implements OnInit {
} }
public canDownload(): boolean { public canDownload(): boolean {
return this.torrent.rdStatus === RealDebridStatus.Finished && this.torrent.downloads.length === 0; return (
(this.torrent.rdStatus === RealDebridStatus.Finished && this.torrent.downloads.length === 0) ||
(this.torrent.downloads.length > 0 && this.torrent.downloads.any((m) => m.error != null))
);
} }
public canUnpack(): boolean { public canUnpack(): boolean {

View file

@ -9,23 +9,19 @@ export class TorrentStatusPipe implements PipeTransform {
constructor(private pipe: FileSizePipe) {} constructor(private pipe: FileSizePipe) {}
transform(torrent: Torrent): string { transform(torrent: Torrent): string {
if (torrent.completed) {
return 'Finished';
}
if (torrent.downloads.length > 0) { if (torrent.downloads.length > 0) {
const allFinished = torrent.downloads.all((m) => m.completed != null);
if (allFinished) {
return 'Finished';
}
const errors = torrent.downloads.where((m) => m.error != null); const errors = torrent.downloads.where((m) => m.error != null);
if (errors.length > 0) { if (errors.length > 0) {
return 'Error'; return 'Error';
} }
const allFinished = torrent.downloads.all((m) => m.completed != null);
if (allFinished) {
return 'Finished';
}
const downloading = torrent.downloads.where((m) => m.downloadStarted && !m.downloadFinished); const downloading = torrent.downloads.where((m) => m.downloadStarted && !m.downloadFinished);
if (downloading.length > 0) { if (downloading.length > 0) {
@ -80,6 +76,10 @@ export class TorrentStatusPipe implements PipeTransform {
} }
} }
if (torrent.completed) {
return 'Finished';
}
switch (torrent.rdStatus) { switch (torrent.rdStatus) {
case RealDebridStatus.Downloading: case RealDebridStatus.Downloading:
const speed = this.pipe.transform(torrent.rdSpeed, 'filesize'); const speed = this.pipe.transform(torrent.rdSpeed, 'filesize');

View file

@ -89,6 +89,11 @@ namespace RdtClient.Data.Data
var dbDownload = await _dataContext.Downloads var dbDownload = await _dataContext.Downloads
.FirstOrDefaultAsync(m => m.DownloadId == downloadId); .FirstOrDefaultAsync(m => m.DownloadId == downloadId);
if (dbDownload == null)
{
return;
}
dbDownload.DownloadFinished = dateTime; dbDownload.DownloadFinished = dateTime;
await _dataContext.SaveChangesAsync(); await _dataContext.SaveChangesAsync();

View file

@ -84,6 +84,7 @@ namespace RdtClient.Service.Services
// Determine the file size // Determine the file size
var webRequest = WebRequest.Create(uri); var webRequest = WebRequest.Create(uri);
webRequest.Method = "HEAD"; webRequest.Method = "HEAD";
webRequest.Timeout = 5000;
Int64 responseLength; Int64 responseLength;
using (var webResponse = await webRequest.GetResponseAsync()) using (var webResponse = await webRequest.GetResponseAsync())
@ -91,36 +92,67 @@ namespace RdtClient.Service.Services
responseLength = Int64.Parse(webResponse.Headers.Get("Content-Length")); responseLength = Int64.Parse(webResponse.Headers.Get("Content-Length"));
} }
var request = WebRequest.Create(uri); var timeout = DateTimeOffset.UtcNow.AddHours(1);
using var response = await request.GetResponseAsync();
await using var stream = response.GetResponseStream(); while (timeout > DateTimeOffset.UtcNow)
await using var fileStream = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.Write);
var buffer = new Byte[4096];
while (fileStream.Length < response.ContentLength)
{ {
var read = await stream.ReadAsync(buffer, 0, buffer.Length); try
if (read > 0)
{ {
fileStream.Write(buffer, 0, read); var request = WebRequest.Create(uri);
using var response = await request.GetResponseAsync();
BytesDone = fileStream.Length; await using var stream = response.GetResponseStream();
BytesTotal = responseLength;
if (DateTime.UtcNow > _nextUpdate) if (stream == null)
{ {
Speed = fileStream.Length - _bytesLastUpdate; throw new IOException("No stream");
_nextUpdate = DateTime.UtcNow.AddSeconds(1);
_bytesLastUpdate = fileStream.Length;
} }
}
else await using var fileStream = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.Write);
{ var buffer = new Byte[4096];
while (fileStream.Length < response.ContentLength)
{
var read = await stream.ReadAsync(buffer, 0, buffer.Length);
if (read > 0)
{
fileStream.Write(buffer, 0, read);
BytesDone = fileStream.Length;
BytesTotal = responseLength;
if (DateTime.UtcNow > _nextUpdate)
{
Speed = fileStream.Length - _bytesLastUpdate;
_nextUpdate = DateTime.UtcNow.AddSeconds(1);
_bytesLastUpdate = fileStream.Length;
timeout = DateTimeOffset.UtcNow.AddHours(1);
}
}
else
{
break;
}
}
break; break;
} }
catch (IOException)
{
await Task.Delay(1000);
}
catch (WebException)
{
await Task.Delay(1000);
}
}
if (timeout <= DateTimeOffset.UtcNow)
{
throw new Exception($"Download timed out");
} }
Speed = 0; Speed = 0;

View file

@ -134,7 +134,7 @@ namespace RdtClient.Service.Services
// Check if there are any downloads that are queued and can be started. // Check if there are any downloads that are queued and can be started.
var queuedDownloads = torrents.SelectMany(m => m.Downloads) var queuedDownloads = torrents.SelectMany(m => m.Downloads)
.Where(m => m.DownloadQueued != null && m.DownloadStarted == null) .Where(m => m.Completed == null && m.DownloadQueued != null && m.DownloadStarted == null)
.OrderBy(m => m.DownloadQueued); .OrderBy(m => m.DownloadQueued);
foreach (var download in queuedDownloads) foreach (var download in queuedDownloads)
@ -144,7 +144,7 @@ namespace RdtClient.Service.Services
// Check if there are any unpacks that are queued and can be started. // Check if there are any unpacks that are queued and can be started.
var queuedUnpacks = torrents.SelectMany(m => m.Downloads) var queuedUnpacks = torrents.SelectMany(m => m.Downloads)
.Where(m => m.UnpackingQueued != null && m.UnpackingStarted == null) .Where(m => m.Completed == null && m.UnpackingQueued != null && m.UnpackingStarted == null)
.OrderBy(m => m.DownloadQueued); .OrderBy(m => m.DownloadQueued);
foreach (var download in queuedUnpacks) foreach (var download in queuedUnpacks)
@ -197,7 +197,8 @@ namespace RdtClient.Service.Services
// If the torrent has any files that need starting to be downloaded, download them. // If the torrent has any files that need starting to be downloaded, download them.
var downloadsPending = torrent.Downloads var downloadsPending = torrent.Downloads
.Where(m => m.DownloadStarted == null && .Where(m => m.Completed == null &&
m.DownloadStarted == null &&
m.DownloadFinished == null) m.DownloadFinished == null)
.ToList(); .ToList();
@ -216,7 +217,8 @@ namespace RdtClient.Service.Services
{ {
// If all files are finished downloading, move to the unpacking step. // If all files are finished downloading, move to the unpacking step.
var unpackingPending = torrent.Downloads var unpackingPending = torrent.Downloads
.Where(m => m.DownloadFinished != null && .Where(m => m.Completed == null &&
m.DownloadFinished != null &&
m.UnpackingStarted == null && m.UnpackingStarted == null &&
m.UnpackingFinished == null) m.UnpackingFinished == null)
.ToList(); .ToList();

View file

@ -214,6 +214,15 @@ namespace RdtClient.Service.Services
var downloadPath = await DownloadPath(download.Torrent); var downloadPath = await DownloadPath(download.Torrent);
download.DownloadFinished = null;
await _downloads.UpdateDownloadStarted(download.DownloadId, null);
download.Completed = null;
await _downloads.UpdateCompleted(download.DownloadId, null);
download.Error = null;
await _downloads.UpdateError(download.DownloadId, null);
// Check if we have reached the download limit, if so queue the download, but don't start it. // Check if we have reached the download limit, if so queue the download, but don't start it.
if (TorrentRunner.ActiveDownloadClients.Count >= settingDownloadLimit) if (TorrentRunner.ActiveDownloadClients.Count >= settingDownloadLimit)
{ {