wabbajack/Wabbajack.Server/Services/ArchiveDownloader.cs

152 lines
6.3 KiB
C#
Raw Normal View History

2020-05-14 04:08:27 +00:00
using System;
2021-09-27 12:42:46 +00:00
using System.Threading;
2020-05-14 04:08:27 +00:00
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Wabbajack.BuildServer;
using Wabbajack.Common;
2021-09-27 12:42:46 +00:00
using Wabbajack.Downloaders;
using Wabbajack.DTOs.DownloadStates;
using Wabbajack.Networking.NexusApi;
using Wabbajack.Paths.IO;
2020-05-14 04:08:27 +00:00
using Wabbajack.Server.DataLayer;
using Wabbajack.Server.DTOs;
namespace Wabbajack.Server.Services
{
public class ArchiveDownloader : AbstractService<ArchiveDownloader, int>
{
private SqlService _sql;
private ArchiveMaintainer _archiveMaintainer;
2021-09-27 12:42:46 +00:00
private NexusApi _nexusClient;
private DiscordWebHook _discord;
2021-09-27 12:42:46 +00:00
private readonly DownloadDispatcher _dispatcher;
private readonly TemporaryFileManager _manager;
2020-05-14 04:08:27 +00:00
2021-09-27 12:42:46 +00:00
public ArchiveDownloader(ILogger<ArchiveDownloader> logger, AppSettings settings, SqlService sql, ArchiveMaintainer archiveMaintainer,
DiscordWebHook discord, QuickSync quickSync, DownloadDispatcher dispatcher, TemporaryFileManager manager)
: base(logger, settings, quickSync, TimeSpan.FromMinutes(10))
2020-05-14 04:08:27 +00:00
{
_sql = sql;
_archiveMaintainer = archiveMaintainer;
_discord = discord;
2021-09-27 12:42:46 +00:00
_dispatcher = dispatcher;
_manager = manager;
2020-05-14 04:08:27 +00:00
}
public override async Task<int> Execute()
{
int count = 0;
while (true)
{
2021-09-27 12:42:46 +00:00
var (_, header) = await _nexusClient.Validate();
bool ignoreNexus = (header.DailyRemaining < 100 && header.HourlyRemaining < 10);
//var ignoreNexus = true;
2020-05-14 11:53:51 +00:00
if (ignoreNexus)
2021-09-27 12:42:46 +00:00
_logger.LogWarning($"Ignoring Nexus Downloads due to low hourly api limit (Daily: {header.DailyRemaining}, Hourly:{header.HourlyRemaining})");
2020-05-14 11:53:51 +00:00
else
2021-09-27 12:42:46 +00:00
_logger.LogInformation($"Looking for any download (Daily: {header.DailyRemaining}, Hourly:{header.HourlyRemaining})");
2020-05-14 04:08:27 +00:00
var nextDownload = await _sql.GetNextPendingDownload(ignoreNexus);
2020-05-14 04:08:27 +00:00
2021-09-27 12:42:46 +00:00
if (nextDownload == default)
2020-05-14 04:08:27 +00:00
break;
2020-06-20 22:51:47 +00:00
_logger.LogInformation($"Checking for previously archived {nextDownload.Archive.Hash}");
2020-05-14 04:08:27 +00:00
if (nextDownload.Archive.Hash != default && _archiveMaintainer.HaveArchive(nextDownload.Archive.Hash))
{
await nextDownload.Finish(_sql);
continue;
}
2021-09-27 12:42:46 +00:00
if (nextDownload.Archive.State is Manual or GameFileSource)
2020-05-14 04:08:27 +00:00
{
await nextDownload.Finish(_sql);
continue;
}
try
{
_logger.Log(LogLevel.Information, $"Downloading {nextDownload.Archive.State.PrimaryKeyString}");
ReportStarting(nextDownload.Archive.State.PrimaryKeyString);
2021-09-27 12:42:46 +00:00
await _discord.Send(Channel.Spam,
new DiscordMessage
{
Content = $"Downloading {nextDownload.Archive.State.PrimaryKeyString}"
});
await _dispatcher.PrepareAll(new[] {nextDownload.Archive.State});
await using var tempPath = _manager.CreateFile();
if (await _dispatcher.Download(nextDownload.Archive, tempPath.Path, CancellationToken.None) == default)
{
_logger.LogError(
$"Downloader returned false for {nextDownload.Archive.State.PrimaryKeyString}");
await nextDownload.Fail(_sql, "Downloader returned false");
continue;
}
2020-05-14 04:08:27 +00:00
2021-09-27 12:42:46 +00:00
var hash = await tempPath.Path.Hash();
2021-09-27 12:42:46 +00:00
if (hash == default || (nextDownload.Archive.Hash != default && hash != nextDownload.Archive.Hash))
2020-05-14 04:08:27 +00:00
{
_logger.Log(LogLevel.Warning,
2021-09-27 12:42:46 +00:00
$"Downloaded archive hashes don't match for {nextDownload.Archive.State.PrimaryKeyString} {nextDownload.Archive.Hash} {nextDownload.Archive.Size} vs {hash} {tempPath.Path.Size()}");
2020-05-14 04:08:27 +00:00
await nextDownload.Fail(_sql, "Invalid Hash");
continue;
}
if (nextDownload.Archive.Size != default &&
2021-09-27 12:42:46 +00:00
tempPath.Path.Size() != nextDownload.Archive.Size)
2020-05-14 04:08:27 +00:00
{
await nextDownload.Fail(_sql, "Invalid Size");
continue;
}
2021-09-27 12:42:46 +00:00
nextDownload.Archive.Hash = hash;
nextDownload.Archive.Size = tempPath.Path.Size();
2020-05-14 04:08:27 +00:00
_logger.Log(LogLevel.Information, $"Archiving {nextDownload.Archive.State.PrimaryKeyString}");
await _archiveMaintainer.Ingest(tempPath.Path);
_logger.Log(LogLevel.Information,
$"Finished Archiving {nextDownload.Archive.State.PrimaryKeyString}");
2020-05-14 04:08:27 +00:00
await nextDownload.Finish(_sql);
2021-09-27 12:42:46 +00:00
await _discord.Send(Channel.Spam,
new DiscordMessage
{
Content = $"Finished downloading {nextDownload.Archive.State.PrimaryKeyString}"
});
2020-05-14 04:08:27 +00:00
}
catch (Exception ex)
{
_logger.Log(LogLevel.Warning, $"Error downloading {nextDownload.Archive.State.PrimaryKeyString}");
2020-05-14 04:08:27 +00:00
await nextDownload.Fail(_sql, ex.ToString());
await _discord.Send(Channel.Spam,
new DiscordMessage
{
Content = $"Error downloading {nextDownload.Archive.State.PrimaryKeyString}"
});
}
finally
{
ReportEnding(nextDownload.Archive.State.PrimaryKeyString);
2020-05-14 04:08:27 +00:00
}
count++;
}
if (count > 0)
{
// Wake the Patch builder up in case it needs to build a patch now
await _quickSync.Notify<PatchBuilder>();
}
2020-05-14 04:08:27 +00:00
return count;
}
}
}