Implement the new usage.
MODIFY
WalletWasabi.Backend/Controllers/BlockchainController.cs
WalletWasabi.Backend/Controllers/BlockchainController.cs
@@ -141,27 +141,12 @@ namespace WalletWasabi.Backend.Controllers
internal async Task<AllFeeEstimate> GetAllFeeEstimateAsync(EstimateSmartFeeMode mode)
{
var cacheKey = $"{nameof(GetAllFeeEstimateAsync)}_{mode}";
+ var cacheOptions = new MemoryCacheEntryOptions { AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(500) };
- if (Cache.TryGetValue(cacheKey, out AllFeeEstimate allFeeEstimate))
- {
- return allFeeEstimate;
- }
- else
- {
- var ret = await RpcClient.EstimateAllFeeAsync(mode, simulateIfRegTest: true, tolerateBitcoinCoreBrainfuck: true);
- Cache.Set(cacheKey, ret, TimeSpan.FromSeconds(500));
- return ret;
- }
-
- // ToDo: fix calling AtomicGetOrCreateAsync from AtomicGetOrCreateAsync
- //return await Cache.AtomicGetOrCreateAsync(
- // cacheKey,
- // entry =>
- // {
- // entry.SetAbsoluteExpiration(TimeSpan.FromSeconds(500));
-
- // return RpcClient.EstimateAllFeeAsync(mode, simulateIfRegTest: true, tolerateBitcoinCoreBrainfuck: true);
- // });
+ return await Cache.AtomicGetOrCreateAsync(
+ cacheKey,
+ cacheOptions,
+ () => RpcClient.EstimateAllFeeAsync(mode, simulateIfRegTest: true, tolerateBitcoinCoreBrainfuck: true));
}
/// <summary>
@@ -198,13 +183,12 @@ namespace WalletWasabi.Backend.Controllers
internal async Task<IEnumerable<string>> GetRawMempoolStringsWithCacheAsync()
{
var cacheKey = $"{nameof(GetRawMempoolStringsWithCacheAsync)}";
+ var cacheOptions = new MemoryCacheEntryOptions { AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(3) };
+
return await Cache.AtomicGetOrCreateAsync(
cacheKey,
- entry =>
- {
- entry.SetAbsoluteExpiration(TimeSpan.FromSeconds(3));
- return GetRawMempoolStringsNoCacheAsync();
- });
+ cacheOptions,
+ () => GetRawMempoolStringsNoCacheAsync());
}
private async Task<IEnumerable<string>> GetRawMempoolStringsNoCacheAsync()
@@ -418,14 +402,12 @@ namespace WalletWasabi.Backend.Controllers
private async Task<EstimateSmartFeeResponse> GetEstimateSmartFeeAsync(int target, EstimateSmartFeeMode mode)
{
var cacheKey = $"{nameof(GetEstimateSmartFeeAsync)}_{target}_{mode}";
+ var cacheOptions = new MemoryCacheEntryOptions { AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(300) };
+
return await Cache.AtomicGetOrCreateAsync(
cacheKey,
- entry =>
- {
- entry.SetAbsoluteExpiration(TimeSpan.FromSeconds(300));
-
- return RpcClient.EstimateSmartFeeAsync(target, mode, simulateIfRegTest: true, tryOtherFeeRates: true);
- });
+ cacheOptions,
+ () => RpcClient.EstimateSmartFeeAsync(target, mode, simulateIfRegTest: true, tryOtherFeeRates: true));
}
[HttpGet("status")]
@@ -435,15 +417,12 @@ namespace WalletWasabi.Backend.Controllers
try
{
var cacheKey = $"{nameof(GetStatusAsync)}";
+ var cacheOptions = new MemoryCacheEntryOptions { AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(30) };
return await Cache.AtomicGetOrCreateAsync(
cacheKey,
- entry =>
- {
- entry.SetAbsoluteExpiration(TimeSpan.FromSeconds(30));
-
- return FetchStatusAsync();
- });
+ cacheOptions,
+ () => FetchStatusAsync());
}
catch (Exception ex)
{

MODIFY
WalletWasabi.Tests/UnitTests/MemoryTests.cs
WalletWasabi.Tests/UnitTests/MemoryTests.cs
@@ -24,17 +24,17 @@ namespace WalletWasabi.Tests.UnitTests
var cache1 = new MemoryCache(new MemoryCacheOptions());
var cache2 = new MemoryCache(new MemoryCacheOptions());
- var result0 = await cache1.AtomicGetOrCreate2Async(
+ var result0 = await cache1.AtomicGetOrCreateAsync(
"the-same-key",
new MemoryCacheEntryOptions { AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(10) },
() => Task.FromResult(ExpensiveComputation("World!")));
- var result1 = await cache2.AtomicGetOrCreate2Async(
+ var result1 = await cache2.AtomicGetOrCreateAsync(
"the-same-other-key",
new MemoryCacheEntryOptions { AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(10) },
() => Task.FromResult(ExpensiveComputation("Lurking Wife!")));
- var result2 = await cache1.AtomicGetOrCreate2Async(
+ var result2 = await cache1.AtomicGetOrCreateAsync(
"the-same-key",
new MemoryCacheEntryOptions { AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(10) },
() => Task.FromResult(ExpensiveComputation("World!")));
@@ -43,7 +43,7 @@ namespace WalletWasabi.Tests.UnitTests
// Make sure AtomicGetOrCreateAsync doesn't fail because another cache is disposed.
cache2.Dispose();
- var result3 = await cache1.AtomicGetOrCreate2Async(
+ var result3 = await cache1.AtomicGetOrCreateAsync(
"the-same-key",
new MemoryCacheEntryOptions { AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(10) },
() => Task.FromResult(ExpensiveComputation("Foo!")));
@@ -51,7 +51,7 @@ namespace WalletWasabi.Tests.UnitTests
Assert.Equal(2, invoked);
// Make sure cache2 call will fail.
- await Assert.ThrowsAsync<ObjectDisposedException>(async () => await cache2.AtomicGetOrCreate2Async(
+ await Assert.ThrowsAsync<ObjectDisposedException>(async () => await cache2.AtomicGetOrCreateAsync(
"the-same-key",
new MemoryCacheEntryOptions { AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(10) },
() => Task.FromResult(ExpensiveComputation("Foo!"))));
@@ -73,17 +73,17 @@ namespace WalletWasabi.Tests.UnitTests
var options = new MemoryCacheEntryOptions { AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(10) };
options.AddExpirationToken(new CancellationChangeToken(expireKey1.Token));
- var result0 = await cache.AtomicGetOrCreate2Async(
+ var result0 = await cache.AtomicGetOrCreateAsync(
"key1",
options,
() => Task.FromResult(ExpensiveComputation("World!")));
- var result1 = await cache.AtomicGetOrCreate2Async(
+ var result1 = await cache.AtomicGetOrCreateAsync(
"key2",
new MemoryCacheEntryOptions { AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(10) },
() => Task.FromResult(ExpensiveComputation("Lurking Wife!")));
- var result2 = await cache.AtomicGetOrCreate2Async(
+ var result2 = await cache.AtomicGetOrCreateAsync(
"key1",
new MemoryCacheEntryOptions { AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(10) },
() => Task.FromResult(ExpensiveComputation("World!")));
@@ -94,12 +94,12 @@ namespace WalletWasabi.Tests.UnitTests
// Make sure key1 expired.
expireKey1.Cancel();
- var result3 = await cache.AtomicGetOrCreate2Async(
+ var result3 = await cache.AtomicGetOrCreateAsync(
"key1",
new MemoryCacheEntryOptions { AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(10) },
() => Task.FromResult(ExpensiveComputation("Foo!")));
- var result4 = await cache.AtomicGetOrCreate2Async(
+ var result4 = await cache.AtomicGetOrCreateAsync(
"key2",
new MemoryCacheEntryOptions { AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(10) },
() => Task.FromResult(ExpensiveComputation("Bar!")));
@@ -128,7 +128,7 @@ namespace WalletWasabi.Tests.UnitTests
var cache = new MemoryCache(new MemoryCacheOptions());
- var task0 = cache.AtomicGetOrCreate2Async(
+ var task0 = cache.AtomicGetOrCreateAsync(
"key1",
new MemoryCacheEntryOptions { AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(60) },
() => WaitUntilTrigger("World!"));
@@ -138,17 +138,17 @@ namespace WalletWasabi.Tests.UnitTests
throw new TimeoutException();
}
- var task1 = cache.AtomicGetOrCreate2Async(
+ var task1 = cache.AtomicGetOrCreateAsync(
"key1",
new MemoryCacheEntryOptions { AbsoluteExpirationRelativeToNow = TimeSpan.FromMilliseconds(60) },
() => Task.FromResult("Should not change to this"));
- var task2 = cache.AtomicGetOrCreate2Async(
+ var task2 = cache.AtomicGetOrCreateAsync(
"key1",
new MemoryCacheEntryOptions { AbsoluteExpirationRelativeToNow = TimeSpan.FromMilliseconds(60) },
() => Task.FromResult("Should not change to this either"));
- var task3 = cache.AtomicGetOrCreate2Async(
+ var task3 = cache.AtomicGetOrCreateAsync(
"key2",
new MemoryCacheEntryOptions { AbsoluteExpirationRelativeToNow = TimeSpan.FromMilliseconds(60) },
() => Task.FromResult("Key2"));
@@ -179,19 +179,19 @@ namespace WalletWasabi.Tests.UnitTests
{
var cache = new MemoryCache(new MemoryCacheOptions());
- var result0 = await cache.AtomicGetOrCreate2Async(
+ var result0 = await cache.AtomicGetOrCreateAsync(
"key1",
new MemoryCacheEntryOptions { AbsoluteExpirationRelativeToNow = TimeSpan.FromMilliseconds(1) },
() => Task.FromResult("This will be expired"));
await Task.Delay(1);
- var result1 = await cache.AtomicGetOrCreate2Async(
+ var result1 = await cache.AtomicGetOrCreateAsync(
"key1",
new MemoryCacheEntryOptions { AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(60) },
() => Task.FromResult("Foo"));
- var result2 = await cache.AtomicGetOrCreate2Async(
+ var result2 = await cache.AtomicGetOrCreateAsync(
"key1",
new MemoryCacheEntryOptions { AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(60) },
() => Task.FromResult("Should not change to this"));
@@ -207,7 +207,7 @@ namespace WalletWasabi.Tests.UnitTests
var leeCalled = 0;
async Task<string> Greet(string who) =>
- await cache.AtomicGetOrCreate2Async(
+ await cache.AtomicGetOrCreateAsync(
$"{nameof(Greet)}{who}",
new MemoryCacheEntryOptions { AbsoluteExpirationRelativeToNow = TimeSpan.FromTicks(1) }, // expires really soon
() =>
@@ -217,7 +217,7 @@ namespace WalletWasabi.Tests.UnitTests
});
async Task<string> GreetMrLee() =>
- await cache.AtomicGetOrCreate2Async(
+ await cache.AtomicGetOrCreateAsync(
"key1",
new MemoryCacheEntryOptions { AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(1) },
() =>

MODIFY
WalletWasabi/BitcoinCore/CachedRpcClient.cs
WalletWasabi/BitcoinCore/CachedRpcClient.cs
@@ -40,147 +40,156 @@ namespace WalletWasabi.BitcoinCore
public override async Task<uint256> GetBestBlockHashAsync()
{
string cacheKey = nameof(GetBestBlockHashAsync);
+ var cacheOptions = new MemoryCacheEntryOptions
+ {
+ Size = 1,
+ AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(4) // The best hash doesn't change so often so, keep in cache for 4 seconds.
+ };
+ cacheOptions.AddExpirationToken(new CancellationChangeToken(TipChangeCancellationTokenSource.Token));
return await Cache.AtomicGetOrCreateAsync(
cacheKey,
- entry =>
- {
- entry.SetSize(1);
- entry.SetAbsoluteExpiration(TimeSpan.FromSeconds(4)); // The best hash doesn't change so often so, keep in cache for 4 seconds.
- entry.AddExpirationToken(new CancellationChangeToken(TipChangeCancellationTokenSource.Token));
-
- return base.GetBestBlockHashAsync();
- }).ConfigureAwait(false);
+ cacheOptions,
+ () => base.GetBestBlockHashAsync()).ConfigureAwait(false);
}
public override async Task<Block> GetBlockAsync(uint256 blockHash)
{
string cacheKey = $"{nameof(GetBlockAsync)}:{blockHash}";
- return await Cache.AtomicGetOrCreateAsync(
- cacheKey,
- entry =>
+ var cacheOptions = new MemoryCacheEntryOptions
{
- entry.SetSize(10);
- entry.SetAbsoluteExpiration(TimeSpan.FromSeconds(4)); // There is a block every 10 minutes in average so, keep in cache for 4 seconds.
+ Size = 10,
+ AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(4) // There is a block every 10 minutes in average so, keep in cache for 4 seconds.
+ };
- return base.GetBlockAsync(blockHash);
- }).ConfigureAwait(false);
+ return await Cache.AtomicGetOrCreateAsync(
+ cacheKey,
+ cacheOptions,
+ () => base.GetBlockAsync(blockHash)).ConfigureAwait(false);
}
public override async Task<Block> GetBlockAsync(uint blockHeight)
{
string cacheKey = $"{nameof(GetBlockAsync)}:{blockHeight}";
- return await Cache.AtomicGetOrCreateAsync(
- cacheKey,
- entry =>
+ var cacheOptions = new MemoryCacheEntryOptions
{
- entry.SetSize(10);
- entry.SetAbsoluteExpiration(TimeSpan.FromSeconds(4)); // There is a block every 10 minutes in average so, keep in cache for 4 seconds.
+ Size = 10,
+ AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(4) // There is a block every 10 minutes in average so, keep in cache for 4 seconds.
+ };
- return base.GetBlockAsync(blockHeight);
- }).ConfigureAwait(false);
+ return await Cache.AtomicGetOrCreateAsync(
+ cacheKey,
+ cacheOptions,
+ () => base.GetBlockAsync(blockHeight)).ConfigureAwait(false);
}
public override async Task<BlockHeader> GetBlockHeaderAsync(uint256 blockHash)
{
string cacheKey = $"{nameof(GetBlockHeaderAsync)}:{blockHash}";
- return await Cache.AtomicGetOrCreateAsync(
- cacheKey,
- entry =>
+ var cacheOptions = new MemoryCacheEntryOptions
{
- entry.SetSize(2);
- entry.SetAbsoluteExpiration(TimeSpan.FromSeconds(4)); // There is a block every 10 minutes in average so, keep in cache for 4 seconds.
+ Size = 2,
+ AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(4) // There is a block every 10 minutes in average so, keep in cache for 4 seconds.
+ };
- return base.GetBlockHeaderAsync(blockHash);
- }).ConfigureAwait(false);
+ return await Cache.AtomicGetOrCreateAsync(
+ cacheKey,
+ cacheOptions,
+ () => base.GetBlockHeaderAsync(blockHash)).ConfigureAwait(false);
}
public override async Task<int> GetBlockCountAsync()
{
string cacheKey = nameof(GetBlockCountAsync);
- return await Cache.AtomicGetOrCreateAsync(
- cacheKey,
- entry =>
+ var cacheOptions = new MemoryCacheEntryOptions
{
- entry.SetSize(1);
- entry.SetAbsoluteExpiration(TimeSpan.FromSeconds(2)); // The blockchain info does not change frequently.
- entry.AddExpirationToken(new CancellationChangeToken(TipChangeCancellationTokenSource.Token));
+ Size = 1,
+ AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(2) // The blockchain info does not change frequently.
+ };
+ cacheOptions.AddExpirationToken(new CancellationChangeToken(TipChangeCancellationTokenSource.Token));
- return base.GetBlockCountAsync();
- }).ConfigureAwait(false);
+ return await Cache.AtomicGetOrCreateAsync(
+ cacheKey,
+ cacheOptions,
+ () => base.GetBlockCountAsync()).ConfigureAwait(false);
}
public override async Task<PeerInfo[]> GetPeersInfoAsync()
{
string cacheKey = nameof(GetPeersInfoAsync);
- return await Cache.AtomicGetOrCreateAsync(
- cacheKey,
- entry =>
+ var cacheOptions = new MemoryCacheEntryOptions
{
- entry.SetSize(2);
- entry.SetAbsoluteExpiration(TimeSpan.FromSeconds(0.5));
+ Size = 2,
+ AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(0.5)
+ };
- return base.GetPeersInfoAsync();
- }).ConfigureAwait(false);
+ return await Cache.AtomicGetOrCreateAsync(
+ cacheKey,
+ cacheOptions,
+ () => base.GetPeersInfoAsync()).ConfigureAwait(false);
}
public override async Task<MempoolEntry> GetMempoolEntryAsync(uint256 txid, bool throwIfNotFound = true)
{
string cacheKey = $"{nameof(GetMempoolEntryAsync)}:{txid}";
- return await Cache.AtomicGetOrCreateAsync(
- cacheKey,
- entry =>
+ var cacheOptions = new MemoryCacheEntryOptions
{
- entry.SetSize(20);
- entry.SetAbsoluteExpiration(TimeSpan.FromSeconds(2));
- entry.AddExpirationToken(new CancellationChangeToken(TipChangeCancellationTokenSource.Token));
+ Size = 20,
+ AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(2)
+ };
+ cacheOptions.AddExpirationToken(new CancellationChangeToken(TipChangeCancellationTokenSource.Token));
- return base.GetMempoolEntryAsync(txid, throwIfNotFound);
- }).ConfigureAwait(false);
+ return await Cache.AtomicGetOrCreateAsync(
+ cacheKey,
+ cacheOptions,
+ () => base.GetMempoolEntryAsync(txid, throwIfNotFound)).ConfigureAwait(false);
}
public override async Task<EstimateSmartFeeResponse> EstimateSmartFeeAsync(int confirmationTarget, EstimateSmartFeeMode estimateMode = EstimateSmartFeeMode.Conservative)
{
string cacheKey = $"{nameof(EstimateSmartFeeAsync)}:{confirmationTarget}:{estimateMode}";
- return await Cache.AtomicGetOrCreateAsync(
- cacheKey,
- entry =>
+ var cacheOptions = new MemoryCacheEntryOptions
{
- entry.SetSize(1);
- entry.SetAbsoluteExpiration(TimeSpan.FromSeconds(4));
- entry.AddExpirationToken(new CancellationChangeToken(TipChangeCancellationTokenSource.Token));
+ Size = 1,
+ AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(4)
+ };
+ cacheOptions.AddExpirationToken(new CancellationChangeToken(TipChangeCancellationTokenSource.Token));
- return base.EstimateSmartFeeAsync(confirmationTarget, estimateMode);
- }).ConfigureAwait(false);
+ return await Cache.AtomicGetOrCreateAsync(
+ cacheKey,
+ cacheOptions,
+ () => base.EstimateSmartFeeAsync(confirmationTarget, estimateMode)).ConfigureAwait(false);
}
public override async Task<uint256[]> GetRawMempoolAsync()
{
string cacheKey = nameof(GetRawMempoolAsync);
- return await Cache.AtomicGetOrCreateAsync(
- cacheKey,
- entry =>
+ var cacheOptions = new MemoryCacheEntryOptions
{
- entry.SetSize(20);
- entry.SetAbsoluteExpiration(TimeSpan.FromSeconds(2));
- entry.AddExpirationToken(new CancellationChangeToken(TipChangeCancellationTokenSource.Token));
+ Size = 20,
+ AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(2)
+ };
+ cacheOptions.AddExpirationToken(new CancellationChangeToken(TipChangeCancellationTokenSource.Token));
- return base.GetRawMempoolAsync();
- }).ConfigureAwait(false);
+ return await Cache.AtomicGetOrCreateAsync(
+ cacheKey,
+ cacheOptions,
+ () => base.GetRawMempoolAsync()).ConfigureAwait(false);
}
public override async Task<GetTxOutResponse> GetTxOutAsync(uint256 txid, int index, bool includeMempool = true)
{
string cacheKey = $"{nameof(GetTxOutAsync)}:{txid}:{index}:{includeMempool}";
- return await Cache.AtomicGetOrCreateAsync(
- cacheKey,
- entry =>
+ var cacheOptions = new MemoryCacheEntryOptions
{
- entry.SetSize(2);
- entry.SetAbsoluteExpiration(TimeSpan.FromSeconds(2));
+ Size = 2,
+ AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(2)
+ };
- return base.GetTxOutAsync(txid, index, includeMempool);
- }).ConfigureAwait(false);
+ return await Cache.AtomicGetOrCreateAsync(
+ cacheKey,
+ cacheOptions,
+ () => base.GetTxOutAsync(txid, index, includeMempool)).ConfigureAwait(false);
}
public override async Task<uint256[]> GenerateAsync(int blockCount)

MODIFY
WalletWasabi/Extensions/MemoryExtensions.cs
WalletWasabi/Extensions/MemoryExtensions.cs
@@ -13,53 +13,7 @@ namespace Microsoft.Extensions.Caching.Memory
private static object AsyncLocksLock { get; } = new object();
- public static async Task<TItem> AtomicGetOrCreateAsync<TItem>(this IMemoryCache cache, object key, Func<ICacheEntry, Task<TItem>> factory)
- {
- if (cache.TryGetValue(key, out TItem value))
- {
- return value;
- }
-
- AsyncLock asyncLock;
- lock (AsyncLocksLock)
- {
- // If we have no dic for the cache yet then create one.
- if (!AsyncLocks.TryGetValue(cache, out Dictionary<object, AsyncLock> cacheDic))
- {
- cacheDic = new Dictionary<object, AsyncLock>();
- AsyncLocks.Add(cache, cacheDic);
- }
-
- if (!cacheDic.TryGetValue(key, out asyncLock))
- {
- asyncLock = new AsyncLock();
- cacheDic.Add(key, asyncLock);
- }
- }
-
- using (await asyncLock.LockAsync().ConfigureAwait(false))
- {
- if (!cache.TryGetValue(key, out value))
- {
- value = await cache.GetOrCreateAsync(key, factory).ConfigureAwait(false);
- lock (AsyncLocksLock)
- {
- var cacheDic = AsyncLocks[cache];
-
- // Note that if a cache is disposed, then the cleanup will never happen. This should not cause normally issues, but keep in mind.
- // Cleanup the evicted asynclocks.
- foreach (var toRemove in cacheDic.Keys.Where(x => !cache.TryGetValue(x, out _)).ToList())
- {
- cacheDic.Remove(toRemove);
- }
- }
- }
-
- return value;
- }
- }
-
- public static async Task<TItem> AtomicGetOrCreate2Async<TItem>(this IMemoryCache cache, object key, MemoryCacheEntryOptions options, Func<Task<TItem>> factory)
+ public static async Task<TItem> AtomicGetOrCreateAsync<TItem>(this IMemoryCache cache, object key, MemoryCacheEntryOptions options, Func<Task<TItem>> factory)
{
if (cache.TryGetValue(key, out TItem value))
{

MODIFY
WalletWasabi/Wallets/SmartBlockProvider.cs
WalletWasabi/Wallets/SmartBlockProvider.cs
@@ -26,15 +26,16 @@ namespace WalletWasabi.Wallets
public async Task<Block> GetBlockAsync(uint256 blockHash, CancellationToken cancel)
{
string cacheKey = $"{nameof(SmartBlockProvider)}:{nameof(GetBlockAsync)}:{blockHash}";
- return await Cache.AtomicGetOrCreateAsync(
- cacheKey,
- entry =>
+ var cacheOptions = new MemoryCacheEntryOptions
{
- entry.SetSize(10);
- entry.SetSlidingExpiration(TimeSpan.FromSeconds(4));
+ Size = 10,
+ SlidingExpiration = TimeSpan.FromSeconds(4)
+ };
- return InnerBlockProvider.GetBlockAsync(blockHash, cancel);
- }).ConfigureAwait(false);
+ return await Cache.AtomicGetOrCreateAsync(
+ cacheKey,
+ cacheOptions,
+ () => InnerBlockProvider.GetBlockAsync(blockHash, cancel)).ConfigureAwait(false);
}
}
}

Implement the new usage.