private async Task TruncateCacheAsync() { // Shall not truncate cache while reloading data. if (_cacheInitalizationService.InitializationState != CacheInitializationState.Idle) { return; } SlotType activeSlot = await _redisCacheService.GetActiveSlotAsync(_marketType); var tasks = new List <Task>(); foreach (var assetId in _historyRepository.GetStoredAssetPairs()) { foreach (var priceType in Constants.StoredPriceTypes) { foreach (var timeInterval in Constants.InitFromDbIntervals) { int candlesAmount = _amountOfCandlesToStore[timeInterval]; var intervals = _redisCacheService.GetRedisCacheIntervals(timeInterval); foreach (var interval in intervals) { tasks.Add(_redisCacheService.TruncateCacheAsync(assetId, priceType, interval, GetIntervalCandlesAmount(candlesAmount, interval), activeSlot)); } } } } await Task.WhenAll(tasks); }
public async Task InitializeCacheAsync() { // Depending on cache invalidation period and on asset pairs amount, there may be a case when // the invalidation timer fires before the cache loading has stopped. This will be a signal // to skip timer-based invalidation. // Below we combine two approaches: // - we're exporting a fast signal for any timer-based routine that we have already been initializing the cache; // - and we additionally block all the cache-related operations for other parts of code. // The first is needed to avoid queueing of timer events. If we simply use blocks, we will finally face a problem // when cache initialization may become infinitly repeated. The second is important for avoidining a multi-threaded // write operations to the cache: if we've got a candle update set, we need to await for cache fill completion and // then proceed. lock (_initializationStateLocker) { if (InitializationState == CacheInitializationState.InProgress) { return; } InitializationState = CacheInitializationState.InProgress; } await _cacheSem.WaitAsync(); try { _log.Info(nameof(InitializeCacheAsync), "Caching candles history..."); SlotType activeSlot = await _candlesCacheService.GetActiveSlotAsync(_marketType); //initialize cache to inactive slot SlotType initSlot = activeSlot == SlotType.Slot0 ? SlotType.Slot1 : SlotType.Slot0; var assetPairs = await _assetPairsManager.GetAllAsync(); var now = _clock.UtcNow; foreach (var pairs in assetPairs.Where(a => _candlesHistoryRepository.CanStoreAssetPair(a.Id)).Batch(6)) { var tasks = pairs.Select(p => CacheAssetPairCandlesAsync(p, now, initSlot)); await Task.WhenAll(tasks); } await _candlesCacheService.InjectCacheValidityToken(); // Initial validation token set. await _candlesCacheService.SetActiveSlotAsync(_marketType, initSlot); //switch slots _log.Info(nameof(InitializeCacheAsync), "All candles history is cached"); } finally { InitializationState = CacheInitializationState.Idle; _cacheSem.Release(); } }
public Task <SlotType> GetActiveSlotAsync() { return(_candlesCacheService.GetActiveSlotAsync()); }