diff --git a/client/Lykke.Service.Assets.Client/AssetsServiceWithCache.cs b/client/Lykke.Service.Assets.Client/AssetsServiceWithCache.cs
index f418eb41..8bcdcc41 100644
--- a/client/Lykke.Service.Assets.Client/AssetsServiceWithCache.cs
+++ b/client/Lykke.Service.Assets.Client/AssetsServiceWithCache.cs
@@ -1,6 +1,4 @@
-using System;
-using System.Collections.Generic;
-using System.Reactive.Disposables;
+using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Common.Log;
@@ -10,87 +8,44 @@
namespace Lykke.Service.Assets.Client
{
///
- public class AssetsServiceWithCache : IAssetsServiceWithCache
+ internal class AssetsServiceWithCache : IAssetsServiceWithCache
{
- private readonly IAssetsService _assetsService;
private readonly IDictionaryCache _assetsCache;
private readonly IDictionaryCache _assetPairsCache;
private readonly ILog _log;
///
- public AssetsServiceWithCache(IAssetsService assetsService, IDictionaryCache assetsCache, IDictionaryCache assetPairsCache, ILog log)
+ public AssetsServiceWithCache(IDictionaryCache assetsCache, IDictionaryCache assetPairsCache)
{
- _assetsService = assetsService;
_assetsCache = assetsCache;
_assetPairsCache = assetPairsCache;
- _log = log;
}
///
- public async Task> GetAllAssetPairsAsync(CancellationToken cancellationToken = new CancellationToken())
- {
- await _assetPairsCache.EnsureCacheIsUpdatedAsync(() => GetUncachedAssetPairsAsync(cancellationToken));
-
- return _assetPairsCache.GetAll();
- }
+ public Task> GetAllAssetPairsAsync(CancellationToken cancellationToken = new CancellationToken())
+ => _assetPairsCache.GetAll(cancellationToken);
- async Task> IAssetsServiceWithCache.GetAllAssetsAsync(CancellationToken cancellationToken)
- => await GetAllAssetsAsync(false, cancellationToken);
+ Task> IAssetsServiceWithCache.GetAllAssetsAsync(CancellationToken cancellationToken = new CancellationToken())
+ => GetAllAssetsAsync(false, cancellationToken);
///
- public async Task> GetAllAssetsAsync(bool includeNonTradable, CancellationToken cancellationToken = new CancellationToken())
- {
- await _assetsCache.EnsureCacheIsUpdatedAsync(() => GetUncachedAssetsAsync(cancellationToken));
-
- return _assetsCache.GetAll();
- }
+ public Task> GetAllAssetsAsync(bool includeNonTradable, CancellationToken cancellationToken = new CancellationToken())
+ => _assetsCache.GetAll(cancellationToken);
///
- public async Task TryGetAssetAsync(string assetId, CancellationToken cancellationToken = new CancellationToken())
- {
- await _assetsCache.EnsureCacheIsUpdatedAsync(() => GetUncachedAssetsAsync(cancellationToken));
-
- return _assetsCache.TryGet(assetId);
- }
-
- ///
- public async Task TryGetAssetPairAsync(string assetPairId, CancellationToken cancellationToken = new CancellationToken())
- {
- await _assetPairsCache.EnsureCacheIsUpdatedAsync(() => GetUncachedAssetPairsAsync(cancellationToken));
-
- return _assetPairsCache.TryGet(assetPairId);
- }
+ public Task TryGetAssetAsync(string assetId, CancellationToken cancellationToken = new CancellationToken())
+ => _assetsCache.TryGet(assetId, cancellationToken);
///
- public async Task UpdateAssetPairsCacheAsync(CancellationToken cancellationToken = new CancellationToken())
- {
- _assetPairsCache.Update(await GetUncachedAssetPairsAsync(cancellationToken));
- }
+ public Task TryGetAssetPairAsync(string assetPairId, CancellationToken cancellationToken = new CancellationToken())
+ => _assetPairsCache.TryGet(assetPairId, cancellationToken);
///
- public async Task UpdateAssetsCacheAsync(CancellationToken cancellationToken = new CancellationToken())
- {
- _assetsCache.Update(await GetUncachedAssetsAsync(cancellationToken));
- }
+ public Task UpdateAssetPairsCacheAsync(CancellationToken cancellationToken = new CancellationToken())
+ => _assetPairsCache.Reset(cancellationToken);
///
- public IDisposable StartAutoCacheUpdate()
- {
- return new CompositeDisposable
- {
- _assetPairsCache.StartAutoUpdate(nameof(AssetsServiceWithCache), _log, () => GetUncachedAssetPairsAsync(new CancellationToken())),
- _assetsCache.StartAutoUpdate(nameof(AssetsServiceWithCache), _log, () => GetUncachedAssetsAsync(new CancellationToken()))
- };
- }
-
- private async Task> GetUncachedAssetsAsync(CancellationToken cancellationToken)
- {
- return await _assetsService.AssetGetAllAsync(false, cancellationToken);
- }
-
- private async Task> GetUncachedAssetPairsAsync(CancellationToken cancellationToken)
- {
- return await _assetsService.AssetPairGetAllAsync(cancellationToken);
- }
+ public Task UpdateAssetsCacheAsync(CancellationToken cancellationToken = new CancellationToken())
+ => _assetsCache.Reset(cancellationToken);
}
}
diff --git a/client/Lykke.Service.Assets.Client/Cache/DateTimeProvider.cs b/client/Lykke.Service.Assets.Client/Cache/DateTimeProvider.cs
deleted file mode 100644
index 0310a63d..00000000
--- a/client/Lykke.Service.Assets.Client/Cache/DateTimeProvider.cs
+++ /dev/null
@@ -1,9 +0,0 @@
-using System;
-
-namespace Lykke.Service.Assets.Client.Cache
-{
- public class DateTimeProvider : IDateTimeProvider
- {
- public DateTime UtcNow => DateTime.UtcNow;
- }
-}
diff --git a/client/Lykke.Service.Assets.Client/Cache/DictionaryCache.cs b/client/Lykke.Service.Assets.Client/Cache/DictionaryCache.cs
index 1e47c44b..0246d0ee 100644
--- a/client/Lykke.Service.Assets.Client/Cache/DictionaryCache.cs
+++ b/client/Lykke.Service.Assets.Client/Cache/DictionaryCache.cs
@@ -3,96 +3,65 @@
using System;
using System.Collections.Generic;
using System.Linq;
-using System.Reactive.Disposables;
using System.Threading;
using System.Threading.Tasks;
+using Lykke.Common.Cache;
+using Lykke.Service.Assets.Client.Updaters;
namespace Lykke.Service.Assets.Client.Cache
{
- ///
- public class DictionaryCache : IDictionaryCache
+ ///
+ /// Base class for a dictionary cache.
+ ///
+ internal class DictionaryCache : IDictionaryCache
where T : ICacheItem
{
- private readonly IDateTimeProvider _dateTimeProvider;
- private readonly TimeSpan _cacheExpirationPeriod;
+ private const string AllItems = @"AllItems";
+ private readonly OnDemandDataCache> _innerCache;
+ private readonly IUpdater _updater;
+ private readonly TimeSpan _expirationTime;
- private Dictionary _items;
- private DateTime _cacheExpirationMoment;
- private bool _inAutoUpdate;
-
- ///
- public DictionaryCache(IDateTimeProvider dateTimeProvider, TimeSpan cacheExpirationPeriod)
+ ///
+ /// Create new dictionary cache.
+ ///
+ protected DictionaryCache(IUpdater updater, TimeSpan expirationTime)
{
- _items = new Dictionary();
- _cacheExpirationMoment = DateTime.MinValue;
- _dateTimeProvider = dateTimeProvider;
- _cacheExpirationPeriod = cacheExpirationPeriod;
+ _innerCache = new OnDemandDataCache>();
+ _updater = updater;
+ _expirationTime = expirationTime;
}
///
- public IDisposable StartAutoUpdate(string componentName, ILog log, Func>> getAllAsync)
+ public async Task Reset(CancellationToken token)
{
- if (_inAutoUpdate)
- {
- throw new InvalidOperationException("Dictionary is already in auto update mode.");
- }
-
- _inAutoUpdate = true;
- async Task UpdateCache(ITimerTrigger trigger, TimerTriggeredHandlerArgs args, CancellationToken token)
- {
- await Update(getAllAsync);
- }
-
- var timer = new TimerTrigger(componentName, _cacheExpirationPeriod, log, UpdateCache);
- timer.Start();
-
- return Disposable.Create(() =>
- {
- _inAutoUpdate = false;
- timer.Dispose();
- });
+ _innerCache.Remove(AllItems);
+ await GetItems(token);
}
///
- public async Task EnsureCacheIsUpdatedAsync(Func>> getAllItemsAsync)
- {
- if (_inAutoUpdate)
- {
- return;
- }
-
- if (_cacheExpirationMoment < _dateTimeProvider.UtcNow)
- {
- await Update(getAllItemsAsync);
- }
- }
-
- private async Task Update(Func>> getAllItemsAsync)
+ public async Task TryGet(string id, CancellationToken token)
{
- var items = await getAllItemsAsync();
- Update(items);
+ var items = await GetItems(token);
+ items.TryGetValue(id, out var item);
+ return item;
}
///
- public void Update(IEnumerable items)
+ public async Task> GetAll(CancellationToken token)
{
- _items = items.ToDictionary(p => p.Id, p => p);
-
- _cacheExpirationMoment = _dateTimeProvider.UtcNow + _cacheExpirationPeriod;
+ var items = await GetItems(token);
+ return items.Values;
}
- ///
- public T TryGet(string id)
+ private async Task> GetItems(CancellationToken token)
{
- _items.TryGetValue(id, out var pair);
-
- return pair;
- }
+ async Task> Refresh()
+ {
+ var items = await _updater.GetItemsAsync(token);
+ return items.ToDictionary(x => x.Id);
+ }
- ///
- public IReadOnlyCollection GetAll()
- {
- return _items.Values;
+ return await _innerCache.GetOrAddAsync(AllItems, _ => Refresh(), _expirationTime);
}
}
}
diff --git a/client/Lykke.Service.Assets.Client/Cache/ExpiringDictionaryCache.cs b/client/Lykke.Service.Assets.Client/Cache/ExpiringDictionaryCache.cs
new file mode 100644
index 00000000..2696f305
--- /dev/null
+++ b/client/Lykke.Service.Assets.Client/Cache/ExpiringDictionaryCache.cs
@@ -0,0 +1,23 @@
+using System;
+using Lykke.Service.Assets.Client.Updaters;
+
+namespace Lykke.Service.Assets.Client.Cache
+{
+ ///
+ /// Expiring dictionary cache where the cache entry expires after given time.
+ ///
+ /// the type of cached item
+ internal sealed class ExpiringDictionaryCache : DictionaryCache
+ where T : ICacheItem
+ {
+ ///
+ /// Create a new expiring dictionary cache.
+ ///
+ /// expiration time
+ /// item updater
+ public ExpiringDictionaryCache(TimeSpan expirationTime, IUpdater updater)
+ : base(updater, expirationTime)
+ {
+ }
+ }
+}
diff --git a/client/Lykke.Service.Assets.Client/Cache/ICacheItem.cs b/client/Lykke.Service.Assets.Client/Cache/ICacheItem.cs
index d071486d..4f7c944a 100644
--- a/client/Lykke.Service.Assets.Client/Cache/ICacheItem.cs
+++ b/client/Lykke.Service.Assets.Client/Cache/ICacheItem.cs
@@ -1,7 +1,13 @@
namespace Lykke.Service.Assets.Client.Cache
{
- public interface ICacheItem
+ ///
+ /// Cache item {T} in a .
+ ///
+ internal interface ICacheItem
{
+ ///
+ /// The id of the entry
+ ///
string Id { get; }
}
}
diff --git a/client/Lykke.Service.Assets.Client/Cache/IDateTimeProvider .cs b/client/Lykke.Service.Assets.Client/Cache/IDateTimeProvider .cs
deleted file mode 100644
index f84bf8f2..00000000
--- a/client/Lykke.Service.Assets.Client/Cache/IDateTimeProvider .cs
+++ /dev/null
@@ -1,9 +0,0 @@
-using System;
-
-namespace Lykke.Service.Assets.Client.Cache
-{
- public interface IDateTimeProvider
- {
- DateTime UtcNow { get; }
- }
-}
diff --git a/client/Lykke.Service.Assets.Client/Cache/IDictionaryCache.cs b/client/Lykke.Service.Assets.Client/Cache/IDictionaryCache.cs
index a12d9a3a..fb58e463 100644
--- a/client/Lykke.Service.Assets.Client/Cache/IDictionaryCache.cs
+++ b/client/Lykke.Service.Assets.Client/Cache/IDictionaryCache.cs
@@ -1,5 +1,5 @@
-using System;
-using System.Collections.Generic;
+using System.Collections.Generic;
+using System.Threading;
using System.Threading.Tasks;
using Common.Log;
@@ -8,32 +8,22 @@ namespace Lykke.Service.Assets.Client.Cache
///
/// Simple in-memory client side cache.
///
- public interface IDictionaryCache
+ internal interface IDictionaryCache
where T : ICacheItem
{
///
- /// Starts an automatic updater that keeps the cache updated on a background thread.
+ /// Resets the cache.
///
- IDisposable StartAutoUpdate(string componentName, ILog log, Func>> getAllAsync);
-
- ///
- /// Update the cache when cache has expired.
- ///
- Task EnsureCacheIsUpdatedAsync(Func>> getAllAsync);
-
- ///
- /// Update the cache with given data.
- ///
- void Update(IEnumerable items);
+ Task Reset(CancellationToken token);
///
/// Try to get cached item with given id.
///
- T TryGet(string id);
+ Task TryGet(string id, CancellationToken token);
///
/// Get all cached items.
///
- IReadOnlyCollection GetAll();
+ Task> GetAll(CancellationToken token);
}
}
diff --git a/client/Lykke.Service.Assets.Client/Cache/RefreshingDictionaryCache.cs b/client/Lykke.Service.Assets.Client/Cache/RefreshingDictionaryCache.cs
new file mode 100644
index 00000000..8548d67f
--- /dev/null
+++ b/client/Lykke.Service.Assets.Client/Cache/RefreshingDictionaryCache.cs
@@ -0,0 +1,37 @@
+using System;
+using Common;
+using Common.Log;
+using Lykke.Service.Assets.Client.Updaters;
+
+namespace Lykke.Service.Assets.Client.Cache
+{
+ ///
+ /// A dictionary cache that refreshes/synchronizes in the background.
+ ///
+ /// the type of cached item
+ internal sealed class RefreshingDictionaryCache : DictionaryCache, IDisposable
+ where T : ICacheItem
+ {
+ private readonly TimerTrigger _trigger;
+
+ ///
+ /// Creates a new refreshing dictionary cache.
+ ///
+ /// the refresh time
+ /// the item updater
+ /// the lykke log
+ public RefreshingDictionaryCache(TimeSpan refreshTime, IUpdater updater, ILog log)
+ : base(updater, refreshTime.Add(refreshTime))
+ {
+ _trigger = new TimerTrigger(nameof(AssetsService), refreshTime, log,
+ async (x, y, token) => await Reset(token));
+ _trigger.Start();
+ }
+
+ ///
+ public void Dispose()
+ {
+ _trigger?.Dispose();
+ }
+ }
+}
diff --git a/client/Lykke.Service.Assets.Client/IAssetsServiceWithCache.cs b/client/Lykke.Service.Assets.Client/IAssetsServiceWithCache.cs
index 02d7cff2..17ce6729 100644
--- a/client/Lykke.Service.Assets.Client/IAssetsServiceWithCache.cs
+++ b/client/Lykke.Service.Assets.Client/IAssetsServiceWithCache.cs
@@ -46,11 +46,5 @@ public interface IAssetsServiceWithCache
/// Forcibly updates client-side assets cache
///
Task UpdateAssetsCacheAsync(CancellationToken cancellationToken = new CancellationToken());
-
- ///
- /// Starts an automatic update process that will keep the caches updated the background.
- ///
- /// the update process, when disposed the auto update will stop
- IDisposable StartAutoCacheUpdate();
}
}
diff --git a/client/Lykke.Service.Assets.Client/InternalsVisibleTo.cs b/client/Lykke.Service.Assets.Client/InternalsVisibleTo.cs
new file mode 100644
index 00000000..5d280308
--- /dev/null
+++ b/client/Lykke.Service.Assets.Client/InternalsVisibleTo.cs
@@ -0,0 +1,4 @@
+using System.Runtime.CompilerServices;
+
+[assembly: InternalsVisibleTo("Lykke.Service.Assets.Tests")]
+[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]
diff --git a/client/Lykke.Service.Assets.Client/Lykke.Service.Assets.Client.csproj b/client/Lykke.Service.Assets.Client/Lykke.Service.Assets.Client.csproj
index 63ff8fb8..4e588a27 100644
--- a/client/Lykke.Service.Assets.Client/Lykke.Service.Assets.Client.csproj
+++ b/client/Lykke.Service.Assets.Client/Lykke.Service.Assets.Client.csproj
@@ -26,10 +26,7 @@
-
-
-
\ No newline at end of file
diff --git a/client/Lykke.Service.Assets.Client/ServiceCollectionExtensions.cs b/client/Lykke.Service.Assets.Client/ServiceCollectionExtensions.cs
index 7154ecd1..2703d97b 100644
--- a/client/Lykke.Service.Assets.Client/ServiceCollectionExtensions.cs
+++ b/client/Lykke.Service.Assets.Client/ServiceCollectionExtensions.cs
@@ -1,34 +1,58 @@
-using System.Net.Http;
+using System;
+using Common.Log;
+using System.Net.Http;
using Common.Log;
using Lykke.Service.Assets.Client.Cache;
using Lykke.Service.Assets.Client.Models;
+using Lykke.Service.Assets.Client.Updaters;
using Microsoft.Extensions.DependencyInjection;
namespace Lykke.Service.Assets.Client
{
+ ///
+ /// Service registration for client asset services.
+ ///
public static class ServiceCollectionExtensions
{
- public static void RegisterAssetsClient(this IServiceCollection services, AssetServiceSettings settings,
- ILog log)
+ ///
+ /// Register the asset services.
+ ///
+ /// the dependency injection service collection
+ /// the asset settings
+ /// the lykke log
+ /// use expiring caches or use a self refreshing cache for the assets and asset-pairs
+ public static void RegisterAssetsClient(this IServiceCollection services, AssetServiceSettings settings, ILog log, bool autoRefresh = true)
{
- services
- .AddSingleton(x => new AssetsService(settings.BaseUri, new HttpClient()));
+ services.AddSingleton(x => new AssetsService(settings.BaseUri, new HttpClient()));
- services
- .AddSingleton>(x =>
- new DictionaryCache(new DateTimeProvider(), settings.AssetsCacheExpirationPeriod));
+ services.AddTransient>(x => new AssetsUpdater(x.GetService()));
+ services.AddTransient(x => CreateDictionaryCache(x, settings.AssetsCacheExpirationPeriod, log, autoRefresh));
- services
- .AddSingleton>(x =>
- new DictionaryCache(new DateTimeProvider(), settings.AssetPairsCacheExpirationPeriod));
+ services.AddTransient>(x => new AssetPairsUpdater(x.GetService()));
+ services.AddTransient(x => CreateDictionaryCache(x, settings.AssetPairsCacheExpirationPeriod, log, autoRefresh));
- services
- .AddSingleton(x => new AssetsServiceWithCache(
- x.GetService(),
+ services.AddSingleton(x => new AssetsServiceWithCache(
x.GetService>(),
- x.GetService>(),
+ x.GetService>()
+ ));
+ }
+
+ private static IDictionaryCache CreateDictionaryCache(IServiceProvider provider, TimeSpan period, ILog log, bool refreshing)
+ where T : ICacheItem
+ {
+ if (refreshing)
+ {
+ return new RefreshingDictionaryCache(
+ period,
+ provider.GetService>(),
log
- ));
+ );
+ }
+
+ return new ExpiringDictionaryCache(
+ period,
+ provider.GetService>()
+ );
}
}
}
diff --git a/client/Lykke.Service.Assets.Client/Updaters/AssetPairsUpdater.cs b/client/Lykke.Service.Assets.Client/Updaters/AssetPairsUpdater.cs
new file mode 100644
index 00000000..bed42a09
--- /dev/null
+++ b/client/Lykke.Service.Assets.Client/Updaters/AssetPairsUpdater.cs
@@ -0,0 +1,22 @@
+using System.Collections.Generic;
+using System.Threading;
+using System.Threading.Tasks;
+using Lykke.Service.Assets.Client.Models;
+
+namespace Lykke.Service.Assets.Client.Updaters
+{
+ internal class AssetPairsUpdater : IUpdater
+ {
+ private readonly IAssetsService _service;
+
+ public AssetPairsUpdater(IAssetsService service)
+ {
+ _service = service;
+ }
+
+ public async Task> GetItemsAsync(CancellationToken token)
+ {
+ return await _service.AssetPairGetAllAsync(token);
+ }
+ }
+}
diff --git a/client/Lykke.Service.Assets.Client/Updaters/AssetsUpdater.cs b/client/Lykke.Service.Assets.Client/Updaters/AssetsUpdater.cs
new file mode 100644
index 00000000..d62052d6
--- /dev/null
+++ b/client/Lykke.Service.Assets.Client/Updaters/AssetsUpdater.cs
@@ -0,0 +1,22 @@
+using System.Collections.Generic;
+using System.Threading;
+using System.Threading.Tasks;
+using Lykke.Service.Assets.Client.Models;
+
+namespace Lykke.Service.Assets.Client.Updaters
+{
+ internal class AssetsUpdater : IUpdater
+ {
+ private readonly IAssetsService _service;
+
+ public AssetsUpdater(IAssetsService service)
+ {
+ _service = service;
+ }
+
+ public async Task> GetItemsAsync(CancellationToken token)
+ {
+ return await _service.AssetGetAllAsync(false, token);
+ }
+ }
+}
diff --git a/client/Lykke.Service.Assets.Client/Updaters/IUpdater.cs b/client/Lykke.Service.Assets.Client/Updaters/IUpdater.cs
new file mode 100644
index 00000000..1b831f20
--- /dev/null
+++ b/client/Lykke.Service.Assets.Client/Updaters/IUpdater.cs
@@ -0,0 +1,20 @@
+using System.Collections.Generic;
+using System.Threading;
+using System.Threading.Tasks;
+using Lykke.Service.Assets.Client.Cache;
+
+namespace Lykke.Service.Assets.Client.Updaters
+{
+ ///
+ /// Updater of for retrieving the contents of a dictionary cache.
+ ///
+ /// the type of cache entry to retrieve
+ internal interface IUpdater
+ where T : ICacheItem
+ {
+ ///
+ /// Retrieves the cache items.
+ ///
+ Task> GetItemsAsync(CancellationToken token);
+ }
+}
diff --git a/src/Lykke.Service.Assets.Repositories/Lykke.Service.Assets.Repositories.csproj b/src/Lykke.Service.Assets.Repositories/Lykke.Service.Assets.Repositories.csproj
index 6ec47cf9..c64dcb66 100644
--- a/src/Lykke.Service.Assets.Repositories/Lykke.Service.Assets.Repositories.csproj
+++ b/src/Lykke.Service.Assets.Repositories/Lykke.Service.Assets.Repositories.csproj
@@ -5,7 +5,6 @@
-
diff --git a/src/Lykke.Service.Assets.Services/Lykke.Service.Assets.Services.csproj b/src/Lykke.Service.Assets.Services/Lykke.Service.Assets.Services.csproj
index 4348ca10..8aafb12b 100644
--- a/src/Lykke.Service.Assets.Services/Lykke.Service.Assets.Services.csproj
+++ b/src/Lykke.Service.Assets.Services/Lykke.Service.Assets.Services.csproj
@@ -5,7 +5,6 @@
-
diff --git a/src/Lykke.Service.Assets/Lykke.Service.Assets.csproj b/src/Lykke.Service.Assets/Lykke.Service.Assets.csproj
index 23b1dcb8..5872bb95 100644
--- a/src/Lykke.Service.Assets/Lykke.Service.Assets.csproj
+++ b/src/Lykke.Service.Assets/Lykke.Service.Assets.csproj
@@ -13,11 +13,6 @@
1701;1702;1705;1591
-
-
-
-
-
@@ -25,14 +20,8 @@
-
-
-
-
-
-
diff --git a/tests/Lykke.Service.Assets.Tests/Cache/DictionaryCacheTest.cs b/tests/Lykke.Service.Assets.Tests/Cache/DictionaryCacheTest.cs
deleted file mode 100644
index a55326f8..00000000
--- a/tests/Lykke.Service.Assets.Tests/Cache/DictionaryCacheTest.cs
+++ /dev/null
@@ -1,88 +0,0 @@
-using Lykke.Service.Assets.Client.Cache;
-using Microsoft.VisualStudio.TestTools.UnitTesting;
-using Moq;
-using System;
-using System.Collections.Generic;
-using System.Threading;
-using System.Threading.Tasks;
-using Common.Log;
-
-namespace Lykke.Service.Assets.Tests.Cache
-{
- [TestClass]
- public class DictionaryCacheTest
- {
- private int _getItemsCallCount;
-
- [TestInitialize]
- public void Setup()
- {
- _getItemsCallCount = 0;
- }
-
- [TestMethod]
- public async Task TestExpiringCache()
- {
- var date = DateTime.UtcNow;
- var provider = new Mock();
- provider.SetupGet(x => x.UtcNow).Returns(date);
-
- var sot = new DictionaryCache(provider.Object, TimeSpan.FromSeconds(30));
-
- await sot.EnsureCacheIsUpdatedAsync(GetItems);
-
- Assert.IsTrue(sot.GetAll().Count > 0);
- Assert.AreEqual(1, _getItemsCallCount);
-
- provider.SetupGet(x => x.UtcNow).Returns(date.AddMinutes(1));
- await sot.EnsureCacheIsUpdatedAsync(GetItems);
- Assert.AreEqual(2, _getItemsCallCount);
-
- provider.SetupGet(x => x.UtcNow).Returns(date.AddSeconds(29));
-
- await sot.EnsureCacheIsUpdatedAsync(GetItems);
- Assert.AreEqual(2, _getItemsCallCount);
- }
-
- [TestMethod]
- public async Task TestRefreshingCache()
- {
- var date = DateTime.UtcNow;
- var provider = new Mock();
- provider.SetupGet(x => x.UtcNow).Returns(date);
-
- var sot = new DictionaryCache(provider.Object, TimeSpan.FromMilliseconds(100));
- using (sot.StartAutoUpdate("TestRefreshingCache", Mock.Of(), GetItems))
- {
- Assert.IsTrue(sot.GetAll().Count > 0, "Dictionary should be filled after update");
- Assert.AreEqual(1, _getItemsCallCount, "Initial update should be called at start");
-
- await Task.Delay(150);
-
- Assert.AreEqual(2, _getItemsCallCount, "Update should have been called after timer tick");
- }
-
- await Task.Delay(150);
-
- Assert.AreEqual(2, _getItemsCallCount, "Auto update should have stopped after dispose");
- }
-
- private Task> GetItems()
- {
- _getItemsCallCount++;
-
- IEnumerable result = new List
- {
- new CacheItem {Id = "1"},
- new CacheItem {Id = "2"}
- };
-
- return Task.FromResult(result);
- }
-
- private class CacheItem : ICacheItem
- {
- public string Id { get; set; }
- }
- }
-}
diff --git a/tests/Lykke.Service.Assets.Tests/Cache/ExpiringDictionaryCacheTest.cs b/tests/Lykke.Service.Assets.Tests/Cache/ExpiringDictionaryCacheTest.cs
new file mode 100644
index 00000000..4eeaaef3
--- /dev/null
+++ b/tests/Lykke.Service.Assets.Tests/Cache/ExpiringDictionaryCacheTest.cs
@@ -0,0 +1,55 @@
+using System;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using Lykke.Service.Assets.Client.Cache;
+using Lykke.Service.Assets.Client.Updaters;
+using Microsoft.Extensions.Caching.Memory;
+using Microsoft.Extensions.Options;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Moq;
+
+namespace Lykke.Service.Assets.Tests.Cache
+{
+ [TestClass]
+ public class ExpiringDictionaryCacheTest
+ {
+ [TestMethod]
+ public async Task TestExpiringCache()
+ {
+ var items = Enumerable.Range(1, 5).Select(x => new CacheItem { Id = x.ToString() });
+
+ var updater = new Mock>();
+ updater.Setup(x => x.GetItemsAsync(It.IsAny())).Returns(Task.FromResult(items));
+
+ var sot = new ExpiringDictionaryCache(TimeSpan.FromMilliseconds(100), updater.Object);
+
+ var result1 = await sot.GetAll(new CancellationToken());
+ Assert.IsNotNull(result1);
+ Assert.AreEqual(5, result1.Count);
+
+ updater.Verify(x => x.GetItemsAsync(It.IsAny()), Times.Once);
+
+ var result2 = await sot.GetAll(new CancellationToken());
+ Assert.AreSame(result1, result2);
+
+ updater.Verify(x => x.GetItemsAsync(It.IsAny()), Times.Once);
+
+ await Task.Delay(150);
+
+ updater.Verify(x => x.GetItemsAsync(It.IsAny()), Times.Once, @"Cache should expire not auto update");
+
+ var result3 = await sot.GetAll(new CancellationToken());
+ Assert.IsNotNull(result3);
+ Assert.AreEqual(5, result1.Count);
+ Assert.AreNotSame(result1, result3);
+
+ updater.Verify(x => x.GetItemsAsync(It.IsAny()), Times.Exactly(2));
+ }
+
+ public class CacheItem : ICacheItem
+ {
+ public string Id { get; set; }
+ }
+ }
+}
diff --git a/tests/Lykke.Service.Assets.Tests/Cache/RefreshingDictionaryCacheTest.cs b/tests/Lykke.Service.Assets.Tests/Cache/RefreshingDictionaryCacheTest.cs
new file mode 100644
index 00000000..f57fa503
--- /dev/null
+++ b/tests/Lykke.Service.Assets.Tests/Cache/RefreshingDictionaryCacheTest.cs
@@ -0,0 +1,60 @@
+using Lykke.Service.Assets.Client.Cache;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Moq;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using Common.Log;
+using Lykke.Service.Assets.Client.Updaters;
+using Microsoft.Extensions.Caching.Memory;
+using Microsoft.Extensions.Options;
+
+namespace Lykke.Service.Assets.Tests.Cache
+{
+ [TestClass]
+ public class RefreshingDictionaryCacheTest
+ {
+ [TestMethod]
+ public async Task TestRefreshingCache()
+ {
+ var items = Enumerable.Range(1, 5).Select(x => new CacheItem { Id = x.ToString() });
+
+ var updater = new Mock>();
+ updater.Setup(x => x.GetItemsAsync(It.IsAny())).Returns(Task.FromResult(items));
+
+ var sot = new RefreshingDictionaryCache(TimeSpan.FromMilliseconds(100), updater.Object, Mock.Of());
+
+ // Give system some time to update in background
+ await Task.Delay(10);
+
+ updater.Verify(x => x.GetItemsAsync(It.IsAny()), Times.Once, @"Cache should auto initialize");
+
+ var result1 = await sot.GetAll(new CancellationToken());
+ Assert.IsNotNull(result1);
+ Assert.AreEqual(5, result1.Count);
+
+ var result2 = await sot.GetAll(new CancellationToken());
+ Assert.AreSame(result1, result2);
+
+ updater.Verify(x => x.GetItemsAsync(It.IsAny()), Times.Once, @"Cache should not update on GetItems");
+
+ await Task.Delay(125);
+
+ updater.Verify(x => x.GetItemsAsync(It.IsAny()), Times.Exactly(2), @"Cache should update in background");
+
+ var result3 = await sot.GetAll(new CancellationToken());
+ Assert.IsNotNull(result3);
+ Assert.AreEqual(5, result1.Count);
+ Assert.AreNotSame(result1, result3);
+
+ updater.Verify(x => x.GetItemsAsync(It.IsAny()), Times.Exactly(2));
+ }
+
+ public class CacheItem : ICacheItem
+ {
+ public string Id { get; set; }
+ }
+ }
+}