From 9ade449985a858575b4b477321fdef61e6d322e0 Mon Sep 17 00:00:00 2001 From: Timothy Baldridge Date: Tue, 26 May 2020 05:31:11 -0600 Subject: [PATCH] Make all delete operations async --- Wabbajack.Common.Test/PathTests.cs | 2 +- .../CircuitBreaker/WithAutoRetry.cs | 24 +++++++++++++++++++ Wabbajack.Common/Paths.cs | 11 +++++---- Wabbajack.Common/Utils.cs | 10 ++++---- Wabbajack.Lib/ACompiler.cs | 2 +- Wabbajack.Lib/AInstaller.cs | 10 ++++---- .../Downloaders/BethesdaNetDownloader.cs | 2 +- Wabbajack.Lib/MO2Installer.cs | 4 ++-- .../Services/ArchiveMaintainer.cs | 2 +- Wabbajack.Test/EndToEndTests.cs | 2 +- Wabbajack.Test/RestartingDownloadsTests.cs | 2 +- Wabbajack.Test/SanityTests.cs | 2 +- .../VirtualFileSystemTests.cs | 2 +- Wabbajack.VirtualFileSystem/Context.cs | 2 +- Wabbajack/Settings.cs | 4 ++-- 15 files changed, 53 insertions(+), 28 deletions(-) diff --git a/Wabbajack.Common.Test/PathTests.cs b/Wabbajack.Common.Test/PathTests.cs index c5914f1f..8f914136 100644 --- a/Wabbajack.Common.Test/PathTests.cs +++ b/Wabbajack.Common.Test/PathTests.cs @@ -12,7 +12,7 @@ namespace Wabbajack.Common.Test await tempFile.Path.WriteAllTextAsync("Test"); tempFile.Path.SetReadOnly(true); - tempFile.Path.Delete(); + await tempFile.Path.DeleteAsync(); } [Fact] diff --git a/Wabbajack.Common/CircuitBreaker/WithAutoRetry.cs b/Wabbajack.Common/CircuitBreaker/WithAutoRetry.cs index c70a1b43..ce8a9725 100644 --- a/Wabbajack.Common/CircuitBreaker/WithAutoRetry.cs +++ b/Wabbajack.Common/CircuitBreaker/WithAutoRetry.cs @@ -32,6 +32,30 @@ namespace Wabbajack.Common goto TOP; } } + + public static async ValueTask WithAutoRetry(Func f, TimeSpan? delay = null, int? multipler = null, int? maxRetries = null) where TE : Exception + { + int retries = 0; + delay ??= DEFAULT_DELAY; + multipler ??= DEFAULT_DELAY_MULTIPLIER; + maxRetries ??= DEFAULT_RETRIES; + + TOP: + try + { + await f(); + } + catch (TE ex) + { + retries += 1; + if (retries > maxRetries) + throw; + Utils.Log($"(Retry {retries} of {maxRetries}), got exception {ex.Message}, waiting {delay.Value.TotalMilliseconds}ms"); + await Task.Delay(delay.Value); + delay = delay * multipler; + goto TOP; + } + } } } diff --git a/Wabbajack.Common/Paths.cs b/Wabbajack.Common/Paths.cs index 88daac5f..3b51aad9 100644 --- a/Wabbajack.Common/Paths.cs +++ b/Wabbajack.Common/Paths.cs @@ -181,10 +181,10 @@ namespace Wabbajack.Common if (Root != otherPath.Root) { if (otherPath.Exists && overwrite) - otherPath.Delete(); + await otherPath.DeleteAsync(); await CopyToAsync(otherPath); - Delete(); + await DeleteAsync(); return; } File.Move(_path, otherPath._path, overwrite ? MoveOptions.ReplaceExisting : MoveOptions.None); @@ -248,13 +248,14 @@ namespace Wabbajack.Common Directory.CreateDirectory(_path); } - public void Delete() + public async Task DeleteAsync() { if (!IsFile) return; if (IsReadOnly) IsReadOnly = false; - - File.Delete(_path); + + var path = _path; + await CircuitBreaker.WithAutoRetry(async () => File.Delete(path)); } public bool InFolder(AbsolutePath folder) diff --git a/Wabbajack.Common/Utils.cs b/Wabbajack.Common/Utils.cs index 38c7f9dd..a673ea45 100644 --- a/Wabbajack.Common/Utils.cs +++ b/Wabbajack.Common/Utils.cs @@ -89,7 +89,7 @@ namespace Wabbajack.Common { try { - f.Delete(); + f.DeleteAsync().Wait(); success++; } catch (Exception e) @@ -801,7 +801,7 @@ namespace Wabbajack.Common } catch (UnauthorizedAccessException) { - tmpName.Delete(); + await tmpName.DeleteAsync(); } } @@ -929,7 +929,7 @@ namespace Wabbajack.Common size += buffer.Length; } } - file.Delete(); + await file.DeleteAsync(); return size; }); return results.Sum() / seconds; @@ -1086,9 +1086,9 @@ namespace Wabbajack.Common .DistinctUntilChanged(); } - public static void DeleteEncryptedJson(string key) + public static async ValueTask DeleteEncryptedJson(string key) { - Consts.LocalAppDataPath.Combine(key).Delete(); + await Consts.LocalAppDataPath.Combine(key).DeleteAsync(); } public static void StartProcessFromFile(string file) diff --git a/Wabbajack.Lib/ACompiler.cs b/Wabbajack.Lib/ACompiler.cs index 49eb6cd9..bd3b937c 100644 --- a/Wabbajack.Lib/ACompiler.cs +++ b/Wabbajack.Lib/ACompiler.cs @@ -147,7 +147,7 @@ namespace Wabbajack.Lib using (var of = await ModListOutputFolder.Combine("modlist").Create()) ModList.ToJson(of); - ModListOutputFile.Delete(); + await ModListOutputFile.DeleteAsync(); using (var fs = await ModListOutputFile.Create()) { diff --git a/Wabbajack.Lib/AInstaller.cs b/Wabbajack.Lib/AInstaller.cs index 1e074ac0..e82c7781 100644 --- a/Wabbajack.Lib/AInstaller.cs +++ b/Wabbajack.Lib/AInstaller.cs @@ -148,7 +148,7 @@ namespace Wabbajack.Lib { if (to.IsReadOnly) to.IsReadOnly = false; - to.Delete(); + await to.DeleteAsync(); } if (from.Exists) @@ -210,7 +210,7 @@ namespace Wabbajack.Lib var oldData = new MemoryStream(await toFile.ReadAllBytesAsync()); // Remove the file we're about to patch - toFile.Delete(); + await toFile.DeleteAsync(); // Patch it await using (var outStream = await toFile.Create()) @@ -264,7 +264,7 @@ namespace Wabbajack.Lib var ext = Path.GetExtension(archive.Name); var uniqueKey = archive.State.PrimaryKeyString.StringSha256Hex(); outputPath = DownloadFolder.Combine(origName + "_" + uniqueKey + "_" + ext); - outputPath.Delete(); + await outputPath.DeleteAsync(); } } @@ -358,7 +358,7 @@ namespace Wabbajack.Lib UpdateTracker.NextStep("Looking for files to delete"); await OutputFolder.EnumerateFiles() - .PMap(Queue, UpdateTracker, f => + .PMap(Queue, UpdateTracker, async f => { var relativeTo = f.RelativeTo(OutputFolder); Utils.Status($"Checking if ModList file {relativeTo}"); @@ -366,7 +366,7 @@ namespace Wabbajack.Lib return; Utils.Log($"Deleting {relativeTo} it's not part of this ModList"); - f.Delete(); + await f.DeleteAsync(); }); Utils.Log("Cleaning empty folders"); diff --git a/Wabbajack.Lib/Downloaders/BethesdaNetDownloader.cs b/Wabbajack.Lib/Downloaders/BethesdaNetDownloader.cs index 277948ff..b23dbce7 100644 --- a/Wabbajack.Lib/Downloaders/BethesdaNetDownloader.cs +++ b/Wabbajack.Lib/Downloaders/BethesdaNetDownloader.cs @@ -43,7 +43,7 @@ namespace Wabbajack.Lib.Downloaders public BethesdaNetDownloader() { TriggerLogin = ReactiveCommand.CreateFromTask(() => Utils.CatchAndLog(RequestLoginAndCache), IsLoggedIn.Select(b => !b).ObserveOn(RxApp.MainThreadScheduler)); - ClearLogin = ReactiveCommand.Create(() => Utils.DeleteEncryptedJson(DataName), IsLoggedIn.ObserveOn(RxApp.MainThreadScheduler)); + ClearLogin = ReactiveCommand.Create(() => Utils.CatchAndLog(() =>Utils.DeleteEncryptedJson(DataName)), IsLoggedIn.ObserveOn(RxApp.MainThreadScheduler)); } private static async Task RequestLoginAndCache() diff --git a/Wabbajack.Lib/MO2Installer.cs b/Wabbajack.Lib/MO2Installer.cs index 6c0cd7ef..ce717c6e 100644 --- a/Wabbajack.Lib/MO2Installer.cs +++ b/Wabbajack.Lib/MO2Installer.cs @@ -233,7 +233,7 @@ namespace Wabbajack.Lib { Status($"Writing included .meta file {directive.To}"); var outPath = DownloadFolder.Combine(directive.To); - if (outPath.IsFile) outPath.Delete(); + if (outPath.IsFile) await outPath.DeleteAsync(); await outPath.WriteAllBytesAsync(await LoadBytesFromPath(directive.SourceDataID)); }); } @@ -296,7 +296,7 @@ namespace Wabbajack.Lib { Status($"Writing included file {directive.To}"); var outPath = OutputFolder.Combine(directive.To); - outPath.Delete(); + await outPath.DeleteAsync(); switch (directive) { diff --git a/Wabbajack.Server/Services/ArchiveMaintainer.cs b/Wabbajack.Server/Services/ArchiveMaintainer.cs index 632f752c..ca6ac3d1 100644 --- a/Wabbajack.Server/Services/ArchiveMaintainer.cs +++ b/Wabbajack.Server/Services/ArchiveMaintainer.cs @@ -48,7 +48,7 @@ namespace Wabbajack.Server.Services var hash = await file.FileHashAsync(); if (HaveArchive(hash)) { - file.Delete(); + await file.DeleteAsync(); return _archives[hash]; } diff --git a/Wabbajack.Test/EndToEndTests.cs b/Wabbajack.Test/EndToEndTests.cs index f479f657..198da817 100644 --- a/Wabbajack.Test/EndToEndTests.cs +++ b/Wabbajack.Test/EndToEndTests.cs @@ -64,7 +64,7 @@ namespace Wabbajack.Test DownloadAndInstall(Game.SkyrimSpecialEdition, 32359, "Frost Armor HDT")); // We're going to fully patch this mod from another source. - modfiles[3].Download.Delete(); + await modfiles[3].Download.DeleteAsync(); await utils.Configure(); diff --git a/Wabbajack.Test/RestartingDownloadsTests.cs b/Wabbajack.Test/RestartingDownloadsTests.cs index d8602d76..23710795 100644 --- a/Wabbajack.Test/RestartingDownloadsTests.cs +++ b/Wabbajack.Test/RestartingDownloadsTests.cs @@ -78,7 +78,7 @@ namespace Wabbajack.Test Assert.Equal(server.Data, await testFile.Path.ReadAllBytesAsync()); - testFile.Path.Delete(); + await testFile.Path.DeleteAsync(); } public void Dispose() diff --git a/Wabbajack.Test/SanityTests.cs b/Wabbajack.Test/SanityTests.cs index d66ca403..5337a043 100644 --- a/Wabbajack.Test/SanityTests.cs +++ b/Wabbajack.Test/SanityTests.cs @@ -164,7 +164,7 @@ namespace Wabbajack.Test await modifiedPath.WriteAllTextAsync("random data"); var modifiedModified = modifiedPath.LastModified; - deletedPath.Delete(); + await deletedPath.DeleteAsync(); Assert.True(extraPath.Exists); diff --git a/Wabbajack.VirtualFileSystem.Test/VirtualFileSystemTests.cs b/Wabbajack.VirtualFileSystem.Test/VirtualFileSystemTests.cs index d9bfc14d..9d19588e 100644 --- a/Wabbajack.VirtualFileSystem.Test/VirtualFileSystemTests.cs +++ b/Wabbajack.VirtualFileSystem.Test/VirtualFileSystemTests.cs @@ -108,7 +108,7 @@ namespace Wabbajack.VirtualFileSystem.Test Assert.Equal(14, file.Size); Assert.Equal(Hash.FromBase64("qX0GZvIaTKM="), file.Hash); - TEST_TXT.Delete(); + await TEST_TXT.DeleteAsync(); await AddTestRoot(); diff --git a/Wabbajack.VirtualFileSystem/Context.cs b/Wabbajack.VirtualFileSystem/Context.cs index 79e9cdb0..47e50c40 100644 --- a/Wabbajack.VirtualFileSystem/Context.cs +++ b/Wabbajack.VirtualFileSystem/Context.cs @@ -195,7 +195,7 @@ namespace Wabbajack.VirtualFileSystem } catch (IOException) { - filename.Delete(); + await filename.DeleteAsync(); } } diff --git a/Wabbajack/Settings.cs b/Wabbajack/Settings.cs index d1204cf5..88f1c7d3 100644 --- a/Wabbajack/Settings.cs +++ b/Wabbajack/Settings.cs @@ -50,10 +50,10 @@ namespace Wabbajack } var backup = Consts.SettingsFile.AppendToName("-backup"); - backup.Delete(); + await backup.DeleteAsync(); await Consts.SettingsFile.CopyToAsync(backup); - Consts.SettingsFile.Delete(); + await Consts.SettingsFile.DeleteAsync(); return default; }