Пример #1
0
        public CandlesCacheInitalizationService(
            ICandlesCacheSemaphore cacheSem,
            ILogFactory logFactory,
            IAssetPairsManager assetPairsManager,
            IClock clock,
            ICandlesCacheService candlesCacheService,
            ICandlesHistoryRepository candlesHistoryRepository,
            Dictionary <CandleTimeInterval, int> amountOfCandlesToStore,
            MarketType marketType,
            DateTime minDate)
        {
            _cacheSem = cacheSem ?? throw new ArgumentNullException(nameof(cacheSem));

            if (logFactory == null)
            {
                throw new ArgumentNullException(nameof(logFactory));
            }

            _log = logFactory.CreateLog(this);
            _assetPairsManager        = assetPairsManager ?? throw new ArgumentNullException(nameof(assetPairsManager));
            _clock                    = clock ?? throw new ArgumentNullException(nameof(clock));
            _candlesCacheService      = candlesCacheService ?? throw new ArgumentNullException(nameof(candlesCacheService));
            _candlesHistoryRepository = candlesHistoryRepository ?? throw new ArgumentNullException(nameof(candlesHistoryRepository));
            _amountOfCandlesToStore   = amountOfCandlesToStore;
            _marketType               = marketType;
            _minDate                  = minDate;

            InitializationState = CacheInitializationState.Idle;
        }
Пример #2
0
        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();
            }
        }