diff --git a/Wabbajack.Server/DataLayer/Patches.cs b/Wabbajack.Server/DataLayer/Patches.cs index 60eff515..bf81733b 100644 --- a/Wabbajack.Server/DataLayer/Patches.cs +++ b/Wabbajack.Server/DataLayer/Patches.cs @@ -200,5 +200,30 @@ namespace Wabbajack.Server.DataLayer }); } + + public async Task> AllPatchHashes() + { + await using var conn = await Open(); + return (await conn.QueryAsync<(Hash, Hash)>(@"SELECT a1.Hash, a2.Hash + FROM dbo.Patches p + LEFT JOIN dbo.ArchiveDownloads a1 ON a1.Id = p.SrcId + LEFT JOIN dbo.ArchiveDownloads a2 on a2.Id = p.DestId")).ToHashSet(); + } + + public async Task DeletePatchesForHashPair((Hash, Hash) sqlFile) + { + await using var conn = await Open(); + await conn.ExecuteAsync(@"DELETE p + FROM dbo.Patches p + LEFT JOIN dbo.ArchiveDownloads a1 ON a1.Id = p.SrcId + LEFT JOIN dbo.ArchiveDownloads a2 on a2.Id = p.DestId + WHERE a1.Hash = @SrcHash + AND a2.Hash = @DestHash", new + { + SrcHash = sqlFile.Item1, + DestHash = sqlFile.Item2 + }); + + } } } diff --git a/Wabbajack.Server/Services/PatchBuilder.cs b/Wabbajack.Server/Services/PatchBuilder.cs index b0474700..6e97130d 100644 --- a/Wabbajack.Server/Services/PatchBuilder.cs +++ b/Wabbajack.Server/Services/PatchBuilder.cs @@ -1,5 +1,6 @@ using System; using System.IO; +using System.Linq; using System.Net; using System.Threading.Tasks; using FluentFTP; @@ -145,8 +146,26 @@ namespace Wabbajack.Server.Services var pendingPatch = await _sql.GetPendingPatch(); if (pendingPatch != default) break; - } + + var files = await client.GetListingAsync($"{Consts.ArchiveUpdatesCDNFolder}\\"); + _logger.LogInformation($"Found {files.Length} on the CDN"); + + var sqlFiles = await _sql.AllPatchHashes(); + _logger.LogInformation($"Found {sqlFiles.Count} in SQL"); + + var hashPairs = files.Select(f => f.Name).Where(f => f.Contains("_")).Select(p => + { + var lst = p.Split("_", StringSplitOptions.RemoveEmptyEntries).Select(Hash.FromHex).ToArray(); + return (lst[0], lst[1]); + }).ToHashSet(); + + foreach (var sqlFile in sqlFiles.Where(s => !hashPairs.Contains(s))) + { + _logger.LogInformation($"Removing SQL File entry for {sqlFile.Item1} -> {sqlFile.Item2} it's not on the CDN"); + await _sql.DeletePatchesForHashPair(sqlFile); + } + } private async Task UploadToCDN(AbsolutePath patchFile, string patchName)