Implement chunking
MODIFY
WalletWasabi/CoinJoin/Client/CoinJoinProcessor.cs
WalletWasabi/CoinJoin/Client/CoinJoinProcessor.cs
@@ -63,13 +63,12 @@ namespace WalletWasabi.CoinJoin.Client
}
using var client = new WasabiClient(Synchronizer.WasabiClient.TorClient.DestinationUriAction, Synchronizer.WasabiClient.TorClient.TorSocks5EndPoint);
- var unconfirmedCoinJoins = await client.GetTransactionsAsync(Synchronizer.Network, txsNotKnownByAWalletService, CancellationToken.None).ConfigureAwait(false);
- foreach (var tx in unconfirmedCoinJoins)
+ await foreach (Transaction tx in client.GetTransactionsAsync(Synchronizer.Network, txsNotKnownByAWalletService, CancellationToken.None).ConfigureAwait(false))
{
if (RpcClient is null
|| await TryBroadcastTransactionWithRpcAsync(tx).ConfigureAwait(false)
- || (await RpcClient.TestAsync().ConfigureAwait(false) is { })) // If the test throws exception then I believe it, because RPC is down and the backend is the god.
+ || (await RpcClient.TestAsync().ConfigureAwait(false)) is { }) // If the test throws exception then I believe it, because RPC is down and the backend is the god.
{
BelieveTransaction(tx);
}

MODIFY
WalletWasabi/Extensions/LinqExtensions.cs
WalletWasabi/Extensions/LinqExtensions.cs
@@ -170,5 +170,16 @@ namespace System.Linq
=> me
.OrderByBlockchain()
.Select(x => x.ToLine());
+
+ /// <summary>
+ /// https://stackoverflow.com/a/24087164/2061103
+ /// </summary>
+ public static IEnumerable<IEnumerable<T>> ChunkBy<T>(this IEnumerable<T> source, int chunkSize)
+ {
+ return source
+ .Select((x, i) => new { Index = i, Value = x })
+ .GroupBy(x => x.Index / chunkSize)
+ .Select(x => x.Select(v => v.Value));
+ }
}
}

MODIFY
WalletWasabi/WebClients/Wasabi/WasabiClient.cs
WalletWasabi/WebClients/Wasabi/WasabiClient.cs
@@ -5,6 +5,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
+using System.Runtime.CompilerServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
@@ -84,17 +85,17 @@ namespace WalletWasabi.WebClients.Wasabi
public static Dictionary<uint256, Transaction> TransactionCache { get; } = new Dictionary<uint256, Transaction>();
public static object TransactionCacheLock { get; } = new object();
- public async Task<IEnumerable<Transaction>> GetTransactionsAsync(Network network, IEnumerable<uint256> txHashes, CancellationToken cancel)
+ public async IAsyncEnumerable<Transaction> GetTransactionsAsync(Network network, IEnumerable<uint256> txHashes, [EnumeratorCancellation] CancellationToken cancel)
+ {
+ foreach (IEnumerable<uint256> chunk in txHashes.ChunkBy(10))
{
- // todo: handle max 10tx
-
var allTxs = new List<Transaction>();
var txHashesToQuery = new List<uint256>();
lock (TransactionCacheLock)
{
- var cachedTxs = TransactionCache.Where(x => txHashes.Contains(x.Key));
+ var cachedTxs = TransactionCache.Where(x => chunk.Contains(x.Key));
allTxs.AddRange(cachedTxs.Select(x => x.Value));
- txHashesToQuery.AddRange(txHashes.Except(cachedTxs.Select(x => x.Key)));
+ txHashesToQuery.AddRange(chunk.Except(cachedTxs.Select(x => x.Key)));
}
using var response = await TorClient.SendAndRetryAsync(
@@ -124,7 +125,13 @@ namespace WalletWasabi.WebClients.Wasabi
}
allTxs.AddRange(ret);
- return allTxs.ToDependencyGraph().OrderByDependency();
+ foreach (var tx in allTxs.ToDependencyGraph().OrderByDependency())
+ {
+ yield return tx;
+ }
+
+ cancel.ThrowIfCancellationRequested();
+ }
}
public async Task<IDictionary<int, FeeEstimationPair>> GetFeesAsync(params int[] confirmationTargets)

Implement chunking