mirror of
https://github.com/wabbajack-tools/wabbajack.git
synced 2024-08-30 18:42:17 +00:00
Patch usage tracking, quick waking for polling tasks, several logging tweaks
This commit is contained in:
parent
58022d648e
commit
2d85e96214
@ -4,6 +4,7 @@ using System.Linq;
|
||||
using System.Reactive;
|
||||
using System.Reactive.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using F23.StringSimilarity;
|
||||
using Newtonsoft.Json;
|
||||
using ReactiveUI;
|
||||
using Wabbajack.Common;
|
||||
@ -246,14 +247,16 @@ namespace Wabbajack.Lib.Downloaders
|
||||
var mod = await client.GetModInfo(Game, ModID);
|
||||
var files = await client.GetModFiles(Game, ModID);
|
||||
var oldFile = files.files.FirstOrDefault(f => f.file_id == FileID);
|
||||
var newFile = files.files.Where(f => f.category_name != null).OrderByDescending(f => f.uploaded_timestamp).FirstOrDefault();
|
||||
var nl = new Levenshtein();
|
||||
var newFile = files.files.Where(f => f.category_name != null)
|
||||
.OrderBy(f => nl.Distance(oldFile.name.ToLowerInvariant(), f.name.ToLowerInvariant())).FirstOrDefault();
|
||||
|
||||
if (!mod.available || oldFile == default || newFile == default)
|
||||
{
|
||||
return default;
|
||||
}
|
||||
// Size is in KB
|
||||
if (oldFile.size > 2_500_000 || newFile.size > 2_500_000 || oldFile.file_id == newFile.file_id)
|
||||
if (oldFile.size > 4_500_000 || newFile.size > 4_500_000 || oldFile.file_id == newFile.file_id)
|
||||
{
|
||||
return default;
|
||||
}
|
||||
|
@ -13,6 +13,9 @@
|
||||
<PackageReference Include="CefSharp.OffScreen">
|
||||
<Version>81.3.100</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="F23.StringSimilarity">
|
||||
<Version>3.1.0</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Fody">
|
||||
<Version>6.1.2</Version>
|
||||
</PackageReference>
|
||||
|
@ -560,6 +560,8 @@ CREATE TABLE [dbo].[Patches](
|
||||
[Finished] [datetime] NULL,
|
||||
[IsFailed] [tinyint] NULL,
|
||||
[FailMessage] [varchar](MAX) NULL,
|
||||
[LastUsed] [datetime] NULL,
|
||||
[Downloads] [bigint] NOT NULL DEFAULT 0,
|
||||
CONSTRAINT [PK_Patches] PRIMARY KEY CLUSTERED
|
||||
(
|
||||
[SrcId] ASC,
|
||||
|
@ -15,13 +15,15 @@ namespace Wabbajack.BuildServer.Controllers
|
||||
private SqlService _sql;
|
||||
private DiscordWebHook _discord;
|
||||
private AppSettings _settings;
|
||||
private QuickSync _quickSync;
|
||||
|
||||
public ModUpgrade(ILogger<ModUpgrade> logger, SqlService sql, DiscordWebHook discord, AppSettings settings)
|
||||
public ModUpgrade(ILogger<ModUpgrade> logger, SqlService sql, DiscordWebHook discord, QuickSync quickSync, AppSettings settings)
|
||||
{
|
||||
_logger = logger;
|
||||
_sql = sql;
|
||||
_discord = discord;
|
||||
_settings = settings;
|
||||
_quickSync = quickSync;
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
@ -49,6 +51,7 @@ namespace Wabbajack.BuildServer.Controllers
|
||||
if (patch.PatchSize != 0)
|
||||
{
|
||||
_logger.Log(LogLevel.Information, $"Upgrade requested from {oldDownload.Archive.Hash} to {newDownload.Archive.Hash} patch Found");
|
||||
await _sql.MarkPatchUsage(oldDownload.Id, newDownload.Id);
|
||||
return
|
||||
Ok(
|
||||
$"https://{_settings.BunnyCDN_StorageZone}.b-cdn.net/{Consts.ArchiveUpdatesCDNFolder}/{request.OldArchive.Hash.ToHex()}_{request.NewArchive.Hash.ToHex()}");
|
||||
@ -57,6 +60,16 @@ namespace Wabbajack.BuildServer.Controllers
|
||||
|
||||
return NotFound("Patch creation failed");
|
||||
}
|
||||
|
||||
if (!newDownload.DownloadFinished.HasValue)
|
||||
{
|
||||
await _quickSync.Notify<ArchiveDownloader>();
|
||||
}
|
||||
else
|
||||
{
|
||||
await _quickSync.Notify<PatchBuilder>();
|
||||
}
|
||||
|
||||
_logger.Log(LogLevel.Information, $"Upgrade requested from {oldDownload.Archive.Hash} to {newDownload.Archive.Hash} patch found is processing");
|
||||
// Still processing
|
||||
return Accepted();
|
||||
|
@ -110,7 +110,10 @@ namespace Wabbajack.Server.DataLayer
|
||||
{
|
||||
await using var conn = await Open();
|
||||
var patch = await conn.QueryFirstOrDefaultAsync<(Guid, Guid, long, DateTime?, bool?, string)>(
|
||||
"SELECT SrcId, DestId, PatchSize, Finished, IsFailed, FailMessage FROM dbo.Patches WHERE Finished is NULL");
|
||||
@"SELECT p.SrcId, p.DestId, p.PatchSize, p.Finished, p.IsFailed, p.FailMessage FROM dbo.Patches p
|
||||
LEFT JOIN dbo.ArchiveDownloads src ON src.Id = p.SrcId
|
||||
LEFT JOIN dbo.ArchiveDownloads dest ON dest.Id = p.DestId
|
||||
WHERE p.Finished is NULL AND src.IsFailed = 0 AND dest.IsFailed = 0 ");
|
||||
if (patch == default)
|
||||
return default(Patch);
|
||||
|
||||
@ -144,5 +147,14 @@ namespace Wabbajack.Server.DataLayer
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
public async Task MarkPatchUsage(Guid srcId, Guid destId)
|
||||
{
|
||||
await using var conn = await Open();
|
||||
await conn.ExecuteAsync(
|
||||
@"UPDATE dbo.Patches SET Downloads = Downloads + 1, LastUsed = GETUTCDATE() WHERE SrcId = @srcId AND DestID = @destId",
|
||||
new {SrcId = srcId, DestId = destId});
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -16,12 +16,14 @@ namespace Wabbajack.Server.Services
|
||||
protected AppSettings _settings;
|
||||
private TimeSpan _delay;
|
||||
protected ILogger<TP> _logger;
|
||||
protected QuickSync _quickSync;
|
||||
|
||||
public AbstractService(ILogger<TP> logger, AppSettings settings, TimeSpan delay)
|
||||
public AbstractService(ILogger<TP> logger, AppSettings settings, QuickSync quickSync, TimeSpan delay)
|
||||
{
|
||||
_settings = settings;
|
||||
_delay = delay;
|
||||
_logger = logger;
|
||||
_quickSync = quickSync;
|
||||
}
|
||||
|
||||
public void Start()
|
||||
@ -32,7 +34,7 @@ namespace Wabbajack.Server.Services
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
|
||||
await _quickSync.ResetToken<TP>();
|
||||
try
|
||||
{
|
||||
await Execute();
|
||||
@ -42,9 +44,9 @@ namespace Wabbajack.Server.Services
|
||||
_logger.LogError(ex, "Running Service Loop");
|
||||
}
|
||||
|
||||
await Task.Delay(_delay);
|
||||
var token = await _quickSync.GetToken<TP>();
|
||||
await Task.Delay(_delay, token);
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -16,11 +16,14 @@ namespace Wabbajack.Server.Services
|
||||
private SqlService _sql;
|
||||
private ArchiveMaintainer _archiveMaintainer;
|
||||
private NexusApiClient _nexusClient;
|
||||
private DiscordWebHook _discord;
|
||||
|
||||
public ArchiveDownloader(ILogger<ArchiveDownloader> logger, AppSettings settings, SqlService sql, ArchiveMaintainer archiveMaintainer) : base(logger, settings, TimeSpan.FromMinutes(10))
|
||||
public ArchiveDownloader(ILogger<ArchiveDownloader> logger, AppSettings settings, SqlService sql, ArchiveMaintainer archiveMaintainer, DiscordWebHook discord, QuickSync quickSync)
|
||||
: base(logger, settings, quickSync, TimeSpan.FromMinutes(10))
|
||||
{
|
||||
_sql = sql;
|
||||
_archiveMaintainer = archiveMaintainer;
|
||||
_discord = discord;
|
||||
}
|
||||
|
||||
public override async Task<int> Execute()
|
||||
@ -58,6 +61,7 @@ namespace Wabbajack.Server.Services
|
||||
try
|
||||
{
|
||||
_logger.Log(LogLevel.Information, $"Downloading {nextDownload.Archive.State.PrimaryKeyString}");
|
||||
await _discord.Send(Channel.Spam, new DiscordMessage {Content = $"Downloading {nextDownload.Archive.State.PrimaryKeyString}"});
|
||||
await DownloadDispatcher.PrepareAll(new[] {nextDownload.Archive.State});
|
||||
|
||||
await using var tempPath = new TempFile();
|
||||
@ -86,17 +90,26 @@ namespace Wabbajack.Server.Services
|
||||
|
||||
_logger.Log(LogLevel.Information, $"Finished Archiving {nextDownload.Archive.State.PrimaryKeyString}");
|
||||
await nextDownload.Finish(_sql);
|
||||
await _discord.Send(Channel.Spam, new DiscordMessage {Content = $"Finished downloading {nextDownload.Archive.State.PrimaryKeyString}"});
|
||||
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Log(LogLevel.Warning, $"Error downloading {nextDownload.Archive.State.PrimaryKeyString}");
|
||||
await nextDownload.Fail(_sql, ex.ToString());
|
||||
await _discord.Send(Channel.Spam, new DiscordMessage {Content = $"Error downloading {nextDownload.Archive.State.PrimaryKeyString}"});
|
||||
}
|
||||
|
||||
count++;
|
||||
}
|
||||
|
||||
if (count > 0)
|
||||
{
|
||||
// Wake the Patch builder up in case it needs to build a patch now
|
||||
await _quickSync.Notify<PatchBuilder>();
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ namespace Wabbajack.Server.Services
|
||||
private ILogger<DiscordWebHook> _logger;
|
||||
private Random _random = new Random();
|
||||
|
||||
public DiscordWebHook(ILogger<DiscordWebHook> logger, AppSettings settings) : base(logger, settings, TimeSpan.FromHours(1))
|
||||
public DiscordWebHook(ILogger<DiscordWebHook> logger, AppSettings settings, QuickSync quickSync) : base(logger, settings, quickSync, TimeSpan.FromHours(1))
|
||||
{
|
||||
_settings = settings;
|
||||
_logger = logger;
|
||||
|
@ -30,8 +30,8 @@ namespace Wabbajack.Server.Services
|
||||
new (ModListSummary Summary, DetailedStatus Detailed)[0];
|
||||
|
||||
|
||||
public ListValidator(ILogger<ListValidator> logger, AppSettings settings, SqlService sql, DiscordWebHook discord, NexusKeyMaintainance nexus, ArchiveMaintainer archives)
|
||||
: base(logger, settings, TimeSpan.FromMinutes(5))
|
||||
public ListValidator(ILogger<ListValidator> logger, AppSettings settings, SqlService sql, DiscordWebHook discord, NexusKeyMaintainance nexus, ArchiveMaintainer archives, QuickSync quickSync)
|
||||
: base(logger, settings, quickSync, TimeSpan.FromMinutes(5))
|
||||
{
|
||||
_sql = sql;
|
||||
_discord = discord;
|
||||
@ -56,7 +56,7 @@ namespace Wabbajack.Server.Services
|
||||
{
|
||||
var (_, result) = await ValidateArchive(data, archive);
|
||||
if (result == ArchiveStatus.InValid)
|
||||
return await TryToHeal(data, archive);
|
||||
return await TryToHeal(data, archive, metadata);
|
||||
return (archive, result);
|
||||
});
|
||||
|
||||
@ -133,7 +133,7 @@ namespace Wabbajack.Server.Services
|
||||
}
|
||||
|
||||
private AsyncLock _healLock = new AsyncLock();
|
||||
private async Task<(Archive, ArchiveStatus)> TryToHeal(ValidationData data, Archive archive)
|
||||
private async Task<(Archive, ArchiveStatus)> TryToHeal(ValidationData data, Archive archive, ModlistMetadata modList)
|
||||
{
|
||||
using var _ = await _healLock.WaitAsync();
|
||||
|
||||
@ -182,7 +182,7 @@ namespace Wabbajack.Server.Services
|
||||
await _sql.AddPatch(new Patch {Src = srcDownload, Dest = destDownload});
|
||||
|
||||
_logger.Log(LogLevel.Information, $"Enqueued Patch from {srcDownload.Archive.Hash} to {destDownload.Archive.Hash}");
|
||||
await _discord.Send(Channel.Spam, new DiscordMessage { Content = $"Enqueued Patch from {srcDownload.Archive.Hash} to {destDownload.Archive.Hash}" });
|
||||
await _discord.Send(Channel.Ham, new DiscordMessage { Content = $"Enqueued Patch from {srcDownload.Archive.Hash} to {destDownload.Archive.Hash} to auto-heal `{modList.Links.MachineURL}`" });
|
||||
|
||||
await upgrade.NewFile.DisposeAsync();
|
||||
|
||||
|
@ -13,7 +13,7 @@ namespace Wabbajack.Server.Services
|
||||
{
|
||||
private SqlService _sql;
|
||||
|
||||
public NexusKeyMaintainance(ILogger<NexusKeyMaintainance> logger, AppSettings settings, SqlService sql) : base(logger, settings, TimeSpan.FromHours(1))
|
||||
public NexusKeyMaintainance(ILogger<NexusKeyMaintainance> logger, AppSettings settings, SqlService sql, QuickSync quickSync) : base(logger, settings, quickSync, TimeSpan.FromHours(1))
|
||||
{
|
||||
_sql = sql;
|
||||
}
|
||||
|
@ -16,8 +16,8 @@ namespace Wabbajack.Server.Services
|
||||
{
|
||||
private SqlService _sql;
|
||||
|
||||
public NonNexusDownloadValidator(ILogger<NonNexusDownloadValidator> logger, AppSettings settings, SqlService sql)
|
||||
: base(logger, settings, TimeSpan.FromHours(2))
|
||||
public NonNexusDownloadValidator(ILogger<NonNexusDownloadValidator> logger, AppSettings settings, SqlService sql, QuickSync quickSync)
|
||||
: base(logger, settings, quickSync, TimeSpan.FromHours(2))
|
||||
{
|
||||
_sql = sql;
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ namespace Wabbajack.Server.Services
|
||||
private ArchiveMaintainer _maintainer;
|
||||
|
||||
public PatchBuilder(ILogger<PatchBuilder> logger, SqlService sql, AppSettings settings, ArchiveMaintainer maintainer,
|
||||
DiscordWebHook discordWebHook) : base(logger, settings, TimeSpan.FromMinutes(1))
|
||||
DiscordWebHook discordWebHook, QuickSync quickSync) : base(logger, settings, quickSync, TimeSpan.FromMinutes(1))
|
||||
{
|
||||
_discordWebHook = discordWebHook;
|
||||
_sql = sql;
|
||||
@ -103,6 +103,12 @@ namespace Wabbajack.Server.Services
|
||||
}
|
||||
}
|
||||
|
||||
if (count > 0)
|
||||
{
|
||||
// Notify the List Validator that we may have more patches
|
||||
await _quickSync.Notify<ListValidator>();
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
|
49
Wabbajack.Server/Services/QuickSync.cs
Normal file
49
Wabbajack.Server/Services/QuickSync.cs
Normal file
@ -0,0 +1,49 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Wabbajack.Common;
|
||||
|
||||
namespace Wabbajack.Server.Services
|
||||
{
|
||||
public class QuickSync
|
||||
{
|
||||
private Dictionary<Type, CancellationTokenSource> _syncs = new Dictionary<Type, CancellationTokenSource>();
|
||||
private AsyncLock _lock = new AsyncLock();
|
||||
|
||||
public async Task<CancellationToken> GetToken<T>()
|
||||
{
|
||||
using var _ = await _lock.WaitAsync();
|
||||
if (_syncs.TryGetValue(typeof(T), out var result))
|
||||
{
|
||||
return result.Token;
|
||||
}
|
||||
var token = new CancellationTokenSource();
|
||||
_syncs[typeof(T)] = token;
|
||||
return token.Token;
|
||||
}
|
||||
|
||||
public async Task ResetToken<T>()
|
||||
{
|
||||
using var _ = await _lock.WaitAsync();
|
||||
if (_syncs.TryGetValue(typeof(T), out var ct))
|
||||
{
|
||||
ct.Cancel();
|
||||
}
|
||||
_syncs[typeof(T)] = new CancellationTokenSource();
|
||||
}
|
||||
|
||||
public async Task Notify<T>()
|
||||
{
|
||||
using var _ = await _lock.WaitAsync();
|
||||
if (_syncs.TryGetValue(typeof(T), out var ct))
|
||||
{
|
||||
ct.Cancel();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
@ -55,6 +55,7 @@ namespace Wabbajack.Server
|
||||
});
|
||||
|
||||
services.AddSingleton<AppSettings>();
|
||||
services.AddSingleton<QuickSync>();
|
||||
services.AddSingleton<SqlService>();
|
||||
services.AddSingleton<GlobalInformation>();
|
||||
services.AddSingleton<NexusPoll>();
|
||||
|
Loading…
Reference in New Issue
Block a user