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;