Continue retrying until the phase finishes
MODIFY
WalletWasabi.Tests/UnitTests/WabiSabi/Integration/WabiSabiHttpApiIntegrationTests.cs
WalletWasabi.Tests/UnitTests/WabiSabi/Integration/WabiSabiHttpApiIntegrationTests.cs
@@ -399,9 +399,9 @@ public class WabiSabiHttpApiIntegrationTests : IClassFixture<WabiSabiApiApplicat
var badCoinsTask = Task.Run(async () => await badCoinJoinClient.StartRoundAsync(badCoins, roundState, cts.Token).ConfigureAwait(false), cts.Token);
// BadCoinsTask will throw.
- await Assert.ThrowsAsync<AggregateException>(async () => await Task.WhenAll(new Task[] { badCoinsTask, coinJoinTask }));
+ await Assert.ThrowsAsync<TaskCanceledException>(async () => await Task.WhenAll(new Task[] { badCoinsTask, coinJoinTask }));
- Assert.True(badCoinsTask.IsFaulted);
+ Assert.True(badCoinsTask.IsCanceled);
Assert.True(coinJoinTask.Result.SuccessfulBroadcast);
var broadcastedTx = await transactionCompleted.Task; // wait for the transaction to be broadcasted.

MODIFY
WalletWasabi/WabiSabi/Client/WabiSabiHttpApiClient.cs
WalletWasabi/WabiSabi/Client/WabiSabiHttpApiClient.cs
using System.Collections.Generic;
using System.Linq;
+using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading;
@@ -16,8 +17,6 @@ namespace WalletWasabi.WabiSabi.Client;
public class WabiSabiHttpApiClient : IWabiSabiApiRequestHandler
{
- private const int MaxRetries = 20;
-
private IHttpClient _client;
public WabiSabiHttpApiClient(IHttpClient client)
@@ -64,23 +63,29 @@ public class WabiSabiHttpApiClient : IWabiSabiApiRequestHandler
private async Task<HttpResponseMessage> SendWithRetriesAsync(RemoteAction action, string jsonString, CancellationToken cancellationToken)
{
var exceptions = new List<Exception>();
-
var start = DateTime.UtcNow;
- for (var attempt = 0; attempt < MaxRetries; attempt++)
+ using CancellationTokenSource absoluteTimeoutCts = new(TimeSpan.FromMinutes(30));
+ using CancellationTokenSource linkedCts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, absoluteTimeoutCts.Token);
+ var combinedToken = linkedCts.Token;
+
+ var attempt = 1;
+ do
{
try
{
using StringContent content = new(jsonString, Encoding.UTF8, "application/json");
// Any transport layer errors will throw an exception here.
- HttpResponseMessage response = await _client.SendAsync(HttpMethod.Post, GetUriEndPoint(action), content, cancellationToken).ConfigureAwait(false);
+ HttpResponseMessage response = await _client
+ .SendAsync(HttpMethod.Post, GetUriEndPoint(action), content, combinedToken).ConfigureAwait(false);
TimeSpan totalTime = DateTime.UtcNow - start;
if (exceptions.Any())
{
- Logger.LogDebug($"Received a response for {action} in {totalTime.TotalSeconds:0.##s} after {attempt} failed attempts: {new AggregateException(exceptions)}.");
+ Logger.LogDebug(
+ $"Received a response for {action} in {totalTime.TotalSeconds:0.##s} after {attempt} failed attempts: {new AggregateException(exceptions)}.");
}
else
{
@@ -111,7 +116,8 @@ public class WabiSabiHttpApiClient : IWabiSabiApiRequestHandler
// Wait before the next try.
await Task.Delay(250, cancellationToken).ConfigureAwait(false);
- }
+ attempt++;
+ } while (!combinedToken.IsCancellationRequested);
throw new AggregateException(exceptions);
}

Continue retrying until the phase finishes