From 0960600f0525d7c3e47a26d074636c3a26b79bfd Mon Sep 17 00:00:00 2001 From: Timothy Baldridge Date: Mon, 1 Jun 2020 14:26:03 -0600 Subject: [PATCH] Remove several uses of .Wait --- .../CircuitBreaker/WithAutoRetry.cs | 29 +++++++++++++++++-- Wabbajack.Common/Metrics.cs | 10 ++++--- Wabbajack.Common/Paths.cs | 20 +++++++++---- Wabbajack.Common/Utils.cs | 2 +- .../CriticalFailureIntervention.cs | 6 ++-- Wabbajack.Test/ACompilerTest.cs | 6 ++-- .../View Models/Installers/InstallerVM.cs | 5 ++-- 7 files changed, 57 insertions(+), 21 deletions(-) diff --git a/Wabbajack.Common/CircuitBreaker/WithAutoRetry.cs b/Wabbajack.Common/CircuitBreaker/WithAutoRetry.cs index ce8a9725..50ca8501 100644 --- a/Wabbajack.Common/CircuitBreaker/WithAutoRetry.cs +++ b/Wabbajack.Common/CircuitBreaker/WithAutoRetry.cs @@ -1,4 +1,5 @@ using System; +using System.Threading; using System.Threading.Tasks; namespace Wabbajack.Common @@ -9,7 +10,7 @@ namespace Wabbajack.Common public static int DEFAULT_DELAY_MULTIPLIER = 2; public static int DEFAULT_RETRIES = 5; - public static async ValueTask WithAutoRetry(Func> f, TimeSpan? delay = null, int? multipler = null, int? maxRetries = null) where TE : Exception + public static async ValueTask WithAutoRetryAsync(Func> f, TimeSpan? delay = null, int? multipler = null, int? maxRetries = null) where TE : Exception { int retries = 0; delay ??= DEFAULT_DELAY; @@ -33,7 +34,7 @@ namespace Wabbajack.Common } } - public static async ValueTask WithAutoRetry(Func f, TimeSpan? delay = null, int? multipler = null, int? maxRetries = null) where TE : Exception + public static async ValueTask WithAutoRetryAsync(Func f, TimeSpan? delay = null, int? multipler = null, int? maxRetries = null) where TE : Exception { int retries = 0; delay ??= DEFAULT_DELAY; @@ -56,6 +57,30 @@ namespace Wabbajack.Common goto TOP; } } + + public static void WithAutoRetry(Action 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 + { + 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"); + Thread.Sleep(delay.Value); + delay = delay * multipler; + goto TOP; + } + } } } diff --git a/Wabbajack.Common/Metrics.cs b/Wabbajack.Common/Metrics.cs index 300baa9f..42f9ae69 100644 --- a/Wabbajack.Common/Metrics.cs +++ b/Wabbajack.Common/Metrics.cs @@ -12,13 +12,16 @@ namespace Wabbajack.Common public const string Downloading = "downloading"; public const string BeginInstall = "begin_install"; public const string FinishInstall = "finish_install"; + private static AsyncLock _creationLock = new AsyncLock(); - static Metrics() + public static async ValueTask GetMetricsKey() { + using var _ = await _creationLock.WaitAsync(); if (!Utils.HaveEncryptedJson(Consts.MetricsKeyHeader)) { - Utils.MakeRandomKey().ToEcryptedJson(Consts.MetricsKeyHeader).AsTask().Wait(); + await Utils.MakeRandomKey().ToEcryptedJson(Consts.MetricsKeyHeader); } + return await Utils.FromEncryptedJson(Consts.MetricsKeyHeader); } /// /// This is all we track for metrics, action, and value. The action will be like @@ -31,8 +34,7 @@ namespace Wabbajack.Common var client = new HttpClient(); try { - client.DefaultRequestHeaders.Add(Consts.MetricsKeyHeader, - await Utils.FromEncryptedJson(Consts.MetricsKeyHeader)); + client.DefaultRequestHeaders.Add(Consts.MetricsKeyHeader, await GetMetricsKey()); await client.GetAsync($"{Consts.WabbajackBuildServerUri}metrics/{action}/{value}"); } catch (Exception) diff --git a/Wabbajack.Common/Paths.cs b/Wabbajack.Common/Paths.cs index 62cfb0d9..a7d4219a 100644 --- a/Wabbajack.Common/Paths.cs +++ b/Wabbajack.Common/Paths.cs @@ -95,13 +95,13 @@ namespace Wabbajack.Common public ValueTask Create() { var path = _path; - return CircuitBreaker.WithAutoRetry(async () => File.Open(path, FileMode.Create, FileAccess.ReadWrite)); + return CircuitBreaker.WithAutoRetryAsync(async () => File.Open(path, FileMode.Create, FileAccess.ReadWrite)); } public ValueTask OpenWrite() { var path = _path; - return CircuitBreaker.WithAutoRetry(async () => File.OpenWrite(path)); + return CircuitBreaker.WithAutoRetryAsync(async () => File.OpenWrite(path)); } public async Task WriteAllTextAsync(string text) @@ -255,7 +255,17 @@ namespace Wabbajack.Common if (IsReadOnly) IsReadOnly = false; var path = _path; - await CircuitBreaker.WithAutoRetry(async () => File.Delete(path)); + await CircuitBreaker.WithAutoRetryAsync(async () => File.Delete(path)); + } + + public void Delete() + { + if (!IsFile) return; + + if (IsReadOnly) IsReadOnly = false; + + var path = _path; + CircuitBreaker.WithAutoRetry(async () => File.Delete(path)); } public bool InFolder(AbsolutePath folder) @@ -381,14 +391,14 @@ namespace Wabbajack.Common public ValueTask OpenShared() { var path = _path; - return CircuitBreaker.WithAutoRetry(async () => + return CircuitBreaker.WithAutoRetryAsync(async () => File.Open(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)); } public ValueTask WriteShared() { var path = _path; - return CircuitBreaker.WithAutoRetry(async () => + return CircuitBreaker.WithAutoRetryAsync(async () => File.Open(path, FileMode.Open, FileAccess.Write, FileShare.ReadWrite)); } diff --git a/Wabbajack.Common/Utils.cs b/Wabbajack.Common/Utils.cs index 5eb8d400..c8811ee2 100644 --- a/Wabbajack.Common/Utils.cs +++ b/Wabbajack.Common/Utils.cs @@ -89,7 +89,7 @@ namespace Wabbajack.Common { try { - f.DeleteAsync().Wait(); + f.Delete(); success++; } catch (Exception e) diff --git a/Wabbajack.Lib/StatusMessages/CriticalFailureIntervention.cs b/Wabbajack.Lib/StatusMessages/CriticalFailureIntervention.cs index 2062e95a..8bd5554d 100644 --- a/Wabbajack.Lib/StatusMessages/CriticalFailureIntervention.cs +++ b/Wabbajack.Lib/StatusMessages/CriticalFailureIntervention.cs @@ -1,12 +1,13 @@ using System.Threading.Tasks; using Wabbajack.Common; +using Wabbajack.Common.StatusFeed; namespace Wabbajack.Lib { /// /// This should probably be replaced with an error, but this is just to get messageboxes out of the .Lib library /// - public class CriticalFailureIntervention : AUserIntervention + public class CriticalFailureIntervention : AErrorMessage { private TaskCompletionSource _source = new TaskCompletionSource(); public Task Task => _source.Task; @@ -18,9 +19,8 @@ namespace Wabbajack.Lib } public override string ShortDescription { get; } public override string ExtendedDescription { get; } - public override void Cancel() + public void Cancel() { - Handled = true; _source.SetResult(ConfirmationIntervention.Choice.Abort); } } diff --git a/Wabbajack.Test/ACompilerTest.cs b/Wabbajack.Test/ACompilerTest.cs index a48d50a4..7467253c 100644 --- a/Wabbajack.Test/ACompilerTest.cs +++ b/Wabbajack.Test/ACompilerTest.cs @@ -8,7 +8,7 @@ using Xunit.Abstractions; namespace Wabbajack.Test { - public abstract class ACompilerTest : XunitContextBase, IDisposable + public abstract class ACompilerTest : XunitContextBase, IAsyncDisposable { private IDisposable _unsub; protected TestUtils utils { get; set; } @@ -26,9 +26,9 @@ namespace Wabbajack.Test } - public override void Dispose() + public async ValueTask DisposeAsync() { - utils.DisposeAsync().AsTask().Wait(); + await utils.DisposeAsync(); _unsub.Dispose(); base.Dispose(); } diff --git a/Wabbajack/View Models/Installers/InstallerVM.cs b/Wabbajack/View Models/Installers/InstallerVM.cs index 5ed977d0..02f38734 100644 --- a/Wabbajack/View Models/Installers/InstallerVM.cs +++ b/Wabbajack/View Models/Installers/InstallerVM.cs @@ -102,11 +102,10 @@ namespace Wabbajack { if (Path.GetDirectoryName(Assembly.GetEntryAssembly().Location.ToLower()) == KnownFolders.Downloads.Path.ToLower()) { - Utils.Log(new CriticalFailureIntervention( + Utils.Error(new CriticalFailureIntervention( "Wabbajack is running inside your Downloads folder. This folder is often highly monitored by antivirus software and these can often " + "conflict with the operations Wabbajack needs to perform. Please move this executable outside of your Downloads folder and then restart the app.", - "Cannot run inside Downloads")).Task.Wait(); - Environment.Exit(1); + "Cannot run inside Downloads")); } MWVM = mainWindowVM;