Attempt at fixing parallel context handling errors, simplified symlinkdownloader
This commit is contained in:
parent
becc907061
commit
efe4d04f28
5 changed files with 57 additions and 51 deletions
|
|
@ -210,17 +210,27 @@ public class DownloadData
|
||||||
await TorrentData.VoidCache();
|
await TorrentData.VoidCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task UpdateRemoteId(Guid downloadId, String remoteId)
|
public async Task UpdateRemoteId(Guid downloadId, string remoteId)
|
||||||
{
|
{
|
||||||
var dbDownload = await _dataContext.Downloads
|
await UpdateRemoteIdRange(new Dictionary<Guid, string>
|
||||||
.FirstOrDefaultAsync(m => m.DownloadId == downloadId);
|
|
||||||
|
|
||||||
if (dbDownload == null)
|
|
||||||
{
|
{
|
||||||
return;
|
{ downloadId, remoteId }
|
||||||
}
|
});
|
||||||
|
|
||||||
dbDownload.RemoteId = remoteId;
|
}
|
||||||
|
|
||||||
|
public async Task UpdateRemoteIdRange(Dictionary<Guid, string> remoteIdRange)
|
||||||
|
{
|
||||||
|
foreach (var entry in remoteIdRange)
|
||||||
|
{
|
||||||
|
var dbDownload = await _dataContext.Downloads.FirstOrDefaultAsync(m => m.DownloadId == entry.Key);
|
||||||
|
if (dbDownload == null)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
dbDownload.RemoteId = entry.Value;
|
||||||
|
}
|
||||||
|
|
||||||
await _dataContext.SaveChangesAsync();
|
await _dataContext.SaveChangesAsync();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ public class DownloadClient
|
||||||
public Int64 BytesTotal { get; private set; }
|
public Int64 BytesTotal { get; private set; }
|
||||||
public Int64 BytesDone { get; private set; }
|
public Int64 BytesDone { get; private set; }
|
||||||
|
|
||||||
public DownloadClient(Download download, Torrent torrent, String destinationPath)
|
public DownloadClient(Download download, Torrent torrent, string destinationPath)
|
||||||
{
|
{
|
||||||
_download = download;
|
_download = download;
|
||||||
_torrent = torrent;
|
_torrent = torrent;
|
||||||
|
|
@ -54,7 +54,7 @@ public class DownloadClient
|
||||||
|
|
||||||
await FileHelper.Delete(filePath);
|
await FileHelper.Delete(filePath);
|
||||||
|
|
||||||
Downloader = Settings.Get.DownloadClient.Client switch
|
Downloader = Type switch
|
||||||
{
|
{
|
||||||
Data.Enums.DownloadClient.Internal => new InternalDownloader(_download.Link, filePath),
|
Data.Enums.DownloadClient.Internal => new InternalDownloader(_download.Link, filePath),
|
||||||
Data.Enums.DownloadClient.Aria2c => new Aria2cDownloader(_download.RemoteId, _download.Link, filePath),
|
Data.Enums.DownloadClient.Aria2c => new Aria2cDownloader(_download.RemoteId, _download.Link, filePath),
|
||||||
|
|
|
||||||
|
|
@ -8,9 +8,6 @@ public class SymlinkDownloader : IDownloader
|
||||||
public event EventHandler<DownloadCompleteEventArgs>? DownloadComplete;
|
public event EventHandler<DownloadCompleteEventArgs>? DownloadComplete;
|
||||||
public event EventHandler<DownloadProgressEventArgs>? DownloadProgress;
|
public event EventHandler<DownloadProgressEventArgs>? DownloadProgress;
|
||||||
|
|
||||||
private const Int32 RetryCount = 5;
|
|
||||||
private const Int32 RetryDelaySeconds = 30;
|
|
||||||
|
|
||||||
private readonly String _filePath;
|
private readonly String _filePath;
|
||||||
private readonly String _uri;
|
private readonly String _uri;
|
||||||
|
|
||||||
|
|
@ -26,7 +23,7 @@ public class SymlinkDownloader : IDownloader
|
||||||
_filePath = filePath;
|
_filePath = filePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<String?> Download()
|
public Task<string?> Download()
|
||||||
{
|
{
|
||||||
_logger.Debug($"Starting download of {_uri}, writing to path: {_filePath}");
|
_logger.Debug($"Starting download of {_uri}, writing to path: {_filePath}");
|
||||||
|
|
||||||
|
|
@ -39,48 +36,34 @@ public class SymlinkDownloader : IDownloader
|
||||||
Speed = 0
|
Speed = 0
|
||||||
});
|
});
|
||||||
|
|
||||||
var retryCount = 1;
|
|
||||||
|
|
||||||
while (retryCount < RetryCount)
|
_logger.Debug($"Searching {Settings.Get.DownloadClient.RcloneMountPath} for {fileName}");
|
||||||
|
|
||||||
|
// Recursively search for the fileName in the rclone mount location.
|
||||||
|
var foundFiles = Directory.GetFiles(Settings.Get.DownloadClient.RcloneMountPath, fileName, SearchOption.AllDirectories);
|
||||||
|
|
||||||
|
if (foundFiles.Any())
|
||||||
{
|
{
|
||||||
_logger.Debug($"Searching {Settings.Get.DownloadClient.RcloneMountPath} for {fileName} ({retryCount}/{RetryCount}) ");
|
if (foundFiles.Length > 1)
|
||||||
|
|
||||||
// Recursively search for the fileName in the rclone mount location.
|
|
||||||
var foundFiles = Directory.GetFiles(Settings.Get.DownloadClient.RcloneMountPath, fileName, SearchOption.AllDirectories);
|
|
||||||
|
|
||||||
if (foundFiles.Any())
|
|
||||||
{
|
{
|
||||||
if (foundFiles.Length > 1)
|
_logger.Warning($"Found {foundFiles.Length} files named {fileName}");
|
||||||
{
|
|
||||||
_logger.Warning($"Found {foundFiles.Length} files named {fileName}");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Assume first matching filename is the one we want.
|
|
||||||
var actualFilePath = foundFiles.First();
|
|
||||||
|
|
||||||
var result = TryCreateSymbolicLink(actualFilePath, _filePath);
|
|
||||||
|
|
||||||
if (result)
|
|
||||||
{
|
|
||||||
DownloadComplete?.Invoke(this, new DownloadCompleteEventArgs());
|
|
||||||
|
|
||||||
return actualFilePath;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
await Task.Delay(TimeSpan.FromSeconds(30), _cancellationToken.Token);
|
// Assume first matching filename is the one we want.
|
||||||
|
var actualFilePath = foundFiles.First();
|
||||||
|
|
||||||
retryCount++;
|
var result = TryCreateSymbolicLink(actualFilePath, _filePath);
|
||||||
|
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
DownloadComplete?.Invoke(this, new DownloadCompleteEventArgs());
|
||||||
|
|
||||||
|
return Task.FromResult<string?>(actualFilePath);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_logger.Error($"File '{fileName}' not found after {RetryCount} attempts.");
|
// Return null and try again next cycle.
|
||||||
|
return Task.FromResult<string?>(null);
|
||||||
DownloadComplete?.Invoke(this, new DownloadCompleteEventArgs
|
|
||||||
{
|
|
||||||
Error = $"File '{fileName}' not found after {RetryCount} attempts."
|
|
||||||
});
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task Cancel()
|
public Task Cancel()
|
||||||
|
|
@ -102,7 +85,7 @@ public class SymlinkDownloader : IDownloader
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Boolean TryCreateSymbolicLink(String sourcePath, String symlinkPath)
|
private bool TryCreateSymbolicLink(string sourcePath, string symlinkPath)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -82,6 +82,11 @@ public class Downloads
|
||||||
await _downloadData.UpdateRemoteId(downloadId, remoteId);
|
await _downloadData.UpdateRemoteId(downloadId, remoteId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task UpdateRemoteIdRange(Dictionary<Guid, String> updateDict)
|
||||||
|
{
|
||||||
|
await _downloadData.UpdateRemoteIdRange(updateDict);
|
||||||
|
}
|
||||||
|
|
||||||
public async Task DeleteForTorrent(Guid torrentId)
|
public async Task DeleteForTorrent(Guid torrentId)
|
||||||
{
|
{
|
||||||
await _downloadData.DeleteForTorrent(torrentId);
|
await _downloadData.DeleteForTorrent(torrentId);
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ public class TorrentRunner
|
||||||
private readonly Downloads _downloads;
|
private readonly Downloads _downloads;
|
||||||
private readonly RemoteService _remoteService;
|
private readonly RemoteService _remoteService;
|
||||||
private readonly HttpClient _httpClient;
|
private readonly HttpClient _httpClient;
|
||||||
|
private readonly Dictionary<Guid, string> _aggregatedDownloadResults;
|
||||||
|
|
||||||
public TorrentRunner(ILogger<TorrentRunner> logger, Torrents torrents, Downloads downloads, RemoteService remoteService)
|
public TorrentRunner(ILogger<TorrentRunner> logger, Torrents torrents, Downloads downloads, RemoteService remoteService)
|
||||||
{
|
{
|
||||||
|
|
@ -29,6 +30,7 @@ public class TorrentRunner
|
||||||
_torrents = torrents;
|
_torrents = torrents;
|
||||||
_downloads = downloads;
|
_downloads = downloads;
|
||||||
_remoteService = remoteService;
|
_remoteService = remoteService;
|
||||||
|
_aggregatedDownloadResults = new Dictionary<Guid, string>();
|
||||||
|
|
||||||
_httpClient = new HttpClient
|
_httpClient = new HttpClient
|
||||||
{
|
{
|
||||||
|
|
@ -310,10 +312,16 @@ public class TorrentRunner
|
||||||
.OrderBy(m => m.DownloadQueued)
|
.OrderBy(m => m.DownloadQueued)
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
|
_aggregatedDownloadResults.Clear();
|
||||||
foreach (var download in queuedDownloads)
|
foreach (var download in queuedDownloads)
|
||||||
{
|
{
|
||||||
await ProcessDownload(download, torrent, settingDownloadPath, settingDownloadLimit);
|
await ProcessDownload(download, torrent, settingDownloadPath, settingDownloadLimit);
|
||||||
}
|
}
|
||||||
|
if (_aggregatedDownloadResults.Count > 0)
|
||||||
|
{
|
||||||
|
await _downloads.UpdateRemoteIdRange(_aggregatedDownloadResults);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// 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 = torrent.Downloads
|
var queuedUnpacks = torrent.Downloads
|
||||||
|
|
@ -633,10 +641,10 @@ public class TorrentRunner
|
||||||
|
|
||||||
var remoteId = await downloadClient.Start();
|
var remoteId = await downloadClient.Start();
|
||||||
|
|
||||||
if (!String.IsNullOrWhiteSpace(remoteId) && download.RemoteId != remoteId)
|
if (!string.IsNullOrWhiteSpace(remoteId) && download.RemoteId != remoteId)
|
||||||
{
|
{
|
||||||
Log($"Received ID {remoteId}", download, torrent);
|
Log($"Received ID {remoteId}", download, torrent);
|
||||||
await _downloads.UpdateRemoteId(download.DownloadId, remoteId);
|
_aggregatedDownloadResults.Add(download.DownloadId, remoteId);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue