Added concurrent downloading for symlink downloader
This commit is contained in:
parent
8d16f7fc57
commit
becc907061
3 changed files with 98 additions and 93 deletions
|
|
@ -28,6 +28,8 @@ public class DownloadClient
|
||||||
_download = download;
|
_download = download;
|
||||||
_torrent = torrent;
|
_torrent = torrent;
|
||||||
_destinationPath = destinationPath;
|
_destinationPath = destinationPath;
|
||||||
|
|
||||||
|
Type = Settings.Get.DownloadClient.Client;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<String?> Start()
|
public async Task<String?> Start()
|
||||||
|
|
@ -52,8 +54,6 @@ public class DownloadClient
|
||||||
|
|
||||||
await FileHelper.Delete(filePath);
|
await FileHelper.Delete(filePath);
|
||||||
|
|
||||||
Type = Settings.Get.DownloadClient.Client;
|
|
||||||
|
|
||||||
Downloader = Settings.Get.DownloadClient.Client switch
|
Downloader = Settings.Get.DownloadClient.Client switch
|
||||||
{
|
{
|
||||||
Data.Enums.DownloadClient.Internal => new InternalDownloader(_download.Link, filePath),
|
Data.Enums.DownloadClient.Internal => new InternalDownloader(_download.Link, filePath),
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ public class SymlinkDownloader : IDownloader
|
||||||
public event EventHandler<DownloadProgressEventArgs>? DownloadProgress;
|
public event EventHandler<DownloadProgressEventArgs>? DownloadProgress;
|
||||||
|
|
||||||
private const Int32 RetryCount = 5;
|
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;
|
||||||
|
|
@ -45,13 +46,13 @@ public class SymlinkDownloader : IDownloader
|
||||||
_logger.Debug($"Searching {Settings.Get.DownloadClient.RcloneMountPath} for {fileName} ({retryCount}/{RetryCount}) ");
|
_logger.Debug($"Searching {Settings.Get.DownloadClient.RcloneMountPath} for {fileName} ({retryCount}/{RetryCount}) ");
|
||||||
|
|
||||||
// Recursively search for the fileName in the rclone mount location.
|
// Recursively search for the fileName in the rclone mount location.
|
||||||
var foundFiles = Directory.GetFiles(Settings.Get.DownloadClient.RcloneMountPath, fileName, SearchOption.AllDirectories).ToList();
|
var foundFiles = Directory.GetFiles(Settings.Get.DownloadClient.RcloneMountPath, fileName, SearchOption.AllDirectories);
|
||||||
|
|
||||||
if (foundFiles.Any())
|
if (foundFiles.Any())
|
||||||
{
|
{
|
||||||
if (foundFiles.Count > 1)
|
if (foundFiles.Length > 1)
|
||||||
{
|
{
|
||||||
_logger.Warning($"Found {foundFiles.Count} files named {fileName}");
|
_logger.Warning($"Found {foundFiles.Length} files named {fileName}");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Assume first matching filename is the one we want.
|
// Assume first matching filename is the one we want.
|
||||||
|
|
@ -105,33 +106,21 @@ public class SymlinkDownloader : IDownloader
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var process = new Process();
|
File.CreateSymbolicLink(symlinkPath, sourcePath);
|
||||||
process.StartInfo.FileName = "ln";
|
if (File.Exists(symlinkPath)) // Double-check that the link was created
|
||||||
process.StartInfo.Arguments = @$"-s ""{sourcePath}"" ""{symlinkPath}""";
|
|
||||||
process.StartInfo.UseShellExecute = false;
|
|
||||||
process.StartInfo.RedirectStandardError = true;
|
|
||||||
|
|
||||||
process.Start();
|
|
||||||
|
|
||||||
var errors = process.StandardError.ReadToEnd();
|
|
||||||
|
|
||||||
process.WaitForExit();
|
|
||||||
|
|
||||||
if (process.ExitCode == 0)
|
|
||||||
{
|
{
|
||||||
_logger.Information($"Created symbolic link from {sourcePath} to {symlinkPath}");
|
_logger.Information($"Created symbolic link from {sourcePath} to {symlinkPath}");
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
_logger.Error($"Failed to create symbolic link: {process.ExitCode} - {errors}");
|
{
|
||||||
|
_logger.Error($"Failed to create symbolic link from {sourcePath} to {symlinkPath}");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_logger.Error($"Error creating symbolic link from {sourcePath} to {symlinkPath}: {ex.Message}");
|
_logger.Error($"Error creating symbolic link from {sourcePath} to {symlinkPath}: {ex.Message}");
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -312,75 +312,7 @@ public class TorrentRunner
|
||||||
|
|
||||||
foreach (var download in queuedDownloads)
|
foreach (var download in queuedDownloads)
|
||||||
{
|
{
|
||||||
Log($"Processing to download", download, torrent);
|
await ProcessDownload(download, torrent, settingDownloadPath, settingDownloadLimit);
|
||||||
|
|
||||||
if (ActiveDownloadClients.Count >= settingDownloadLimit)
|
|
||||||
{
|
|
||||||
Log($"Not starting download because there are already the max number of downloads active", download, torrent);
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ActiveDownloadClients.ContainsKey(download.DownloadId))
|
|
||||||
{
|
|
||||||
Log($"Not starting download because this download is already active", download, torrent);
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Log($"Unrestricting links", download, torrent);
|
|
||||||
|
|
||||||
var downloadLink = await _torrents.UnrestrictLink(download.DownloadId);
|
|
||||||
download.Link = downloadLink;
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
_logger.LogError(ex, "Cannot unrestrict link: {ex.Message}", ex.Message);
|
|
||||||
|
|
||||||
await _downloads.UpdateError(download.DownloadId, ex.Message);
|
|
||||||
await _downloads.UpdateCompleted(download.DownloadId, DateTimeOffset.UtcNow);
|
|
||||||
download.Error = ex.Message;
|
|
||||||
download.Completed = DateTimeOffset.UtcNow;
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
Log($"Marking download as started", download, torrent);
|
|
||||||
|
|
||||||
download.DownloadStarted = DateTime.UtcNow;
|
|
||||||
await _downloads.UpdateDownloadStarted(download.DownloadId, download.DownloadStarted);
|
|
||||||
|
|
||||||
var downloadPath = settingDownloadPath;
|
|
||||||
|
|
||||||
if (!String.IsNullOrWhiteSpace(torrent.Category))
|
|
||||||
{
|
|
||||||
downloadPath = Path.Combine(downloadPath, torrent.Category);
|
|
||||||
}
|
|
||||||
|
|
||||||
Log($"Setting download path to {downloadPath}", download, torrent);
|
|
||||||
|
|
||||||
// Start the download process
|
|
||||||
var downloadClient = new DownloadClient(download, torrent, downloadPath);
|
|
||||||
|
|
||||||
if (ActiveDownloadClients.TryAdd(download.DownloadId, downloadClient))
|
|
||||||
{
|
|
||||||
Log($"Starting download", download, torrent);
|
|
||||||
|
|
||||||
var remoteId = await downloadClient.Start();
|
|
||||||
|
|
||||||
if (!String.IsNullOrWhiteSpace(remoteId) && download.RemoteId != remoteId)
|
|
||||||
{
|
|
||||||
Log($"Received ID {remoteId}", download, torrent);
|
|
||||||
|
|
||||||
await _downloads.UpdateRemoteId(download.DownloadId, remoteId);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Log($"No ID received", download, torrent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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.
|
||||||
|
|
@ -628,4 +560,88 @@ public class TorrentRunner
|
||||||
|
|
||||||
_logger.LogError(message);
|
_logger.LogError(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task ProcessDownload(Download download, Torrent torrent, string settingDownloadPath, int settingDownloadLimit)
|
||||||
|
{
|
||||||
|
Log($"Processing to download", download, torrent);
|
||||||
|
|
||||||
|
if (ActiveDownloadClients.Count >= settingDownloadLimit)
|
||||||
|
{
|
||||||
|
Log($"Not starting download because there are already the max number of downloads active", download, torrent);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ActiveDownloadClients.ContainsKey(download.DownloadId))
|
||||||
|
{
|
||||||
|
Log($"Not starting download because this download is already active", download, torrent);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Log($"Unrestricting links", download, torrent);
|
||||||
|
|
||||||
|
var downloadLink = await _torrents.UnrestrictLink(download.DownloadId);
|
||||||
|
download.Link = downloadLink;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "Cannot unrestrict link: {ex.Message}", ex.Message);
|
||||||
|
|
||||||
|
await _downloads.UpdateError(download.DownloadId, ex.Message);
|
||||||
|
await _downloads.UpdateCompleted(download.DownloadId, DateTimeOffset.UtcNow);
|
||||||
|
download.Error = ex.Message;
|
||||||
|
download.Completed = DateTimeOffset.UtcNow;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Log($"Marking download as started", download, torrent);
|
||||||
|
|
||||||
|
download.DownloadStarted = DateTime.UtcNow;
|
||||||
|
await _downloads.UpdateDownloadStarted(download.DownloadId, download.DownloadStarted);
|
||||||
|
|
||||||
|
var downloadPath = settingDownloadPath;
|
||||||
|
|
||||||
|
if (!String.IsNullOrWhiteSpace(torrent.Category))
|
||||||
|
{
|
||||||
|
downloadPath = Path.Combine(downloadPath, torrent.Category);
|
||||||
|
}
|
||||||
|
|
||||||
|
Log($"Setting download path to {downloadPath}", download, torrent);
|
||||||
|
|
||||||
|
var downloadClient = new DownloadClient(download, torrent, downloadPath);
|
||||||
|
|
||||||
|
if (downloadClient.Type == Data.Enums.DownloadClient.Symlink) // Check if the type is "Symlink"
|
||||||
|
{
|
||||||
|
// If it's Symlink type, start the download concurrently
|
||||||
|
_ = Task.Run(async () => await StartDownload(download, torrent, downloadClient));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
await StartDownload(download, torrent, downloadClient);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task StartDownload(Download download, Torrent torrent, DownloadClient downloadClient)
|
||||||
|
{
|
||||||
|
if (ActiveDownloadClients.TryAdd(download.DownloadId, downloadClient))
|
||||||
|
{
|
||||||
|
Log($"Starting download", download, torrent);
|
||||||
|
|
||||||
|
var remoteId = await downloadClient.Start();
|
||||||
|
|
||||||
|
if (!String.IsNullOrWhiteSpace(remoteId) && download.RemoteId != remoteId)
|
||||||
|
{
|
||||||
|
Log($"Received ID {remoteId}", download, torrent);
|
||||||
|
await _downloads.UpdateRemoteId(download.DownloadId, remoteId);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Log($"No ID received", download, torrent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Loading…
Reference in a new issue