/// <summary>
        /// Deletes the item from cache
        /// </summary>
        /// <param name="id">A string representing the id of the item in the cache to be deleted</param>
        /// <param name="cacheItemType">A cache item type</param>
        public override void CacheDeleteItem(string id, CacheItemType cacheItemType)
        {
            if (cacheItemType == CacheItemType.All || cacheItemType == CacheItemType.MarketDescription)
            {
                try
                {
                    foreach (var fetchedVariant in _fetchedVariants)
                    {
                        if (fetchedVariant.Key.StartsWith(id))
                        {
                            _fetchedVariants.TryRemove(id, out _);
                        }
                    }
                }
                catch (Exception e)
                {
                    ExecutionLog.Warn($"Error deleting fetchedVariants for {id}", e);
                }

                if (_cache.Contains(id))
                {
                    CacheLog.Debug($"Delete variant market: {id}");
                    _cache.Remove(id);
                }
            }
        }
예제 #2
0
        /// <summary>
        /// Asynchronously gets a <see cref="SportData"/> representing sport associated with the tournament specified by it's id. Note that the hierarchy will only contain the
        /// specified tournament and it's parent category not all categories / tournaments in the hierarchy
        /// </summary>
        /// <param name="tournamentId">A <see cref="URN"/> specifying the id of the tournament whose parent sport should be retrieved</param>
        /// <param name="cultures">A <see cref="IEnumerable{CultureInfo}"/> specifying the languages in which the data is returned</param>
        /// <returns>A <see cref="Task{SportData}"/> representing the asynchronous operation</returns>
        public async Task <SportData> GetSportForTournamentAsync(URN tournamentId, IEnumerable <CultureInfo> cultures)
        {
            Metric.Context("CACHE").Meter("SportDataCache->GetSportForTournamentAsync", Unit.Calls).Mark();

            var cultureList = cultures as IList <CultureInfo> ?? cultures.ToList();

            if (!await _semaphore.WaitAsyncSafe().ConfigureAwait(false))
            {
                return(null);
            }

            var missingCultures = cultureList.Where(c => !FetchedCultures.Contains(c)).ToList();

            try
            {
                if (missingCultures.Any())
                {
                    await FetchAndMergeAll(missingCultures, false).ConfigureAwait(false);
                }
                //return GetSportForTournamentFromCache(tournamentId, cultureList, false);
            }
            catch (Exception ex)
            {
                ExecutionLog.Warn($"An exception occurred while attempting to fetch sport data for tournament: id={tournamentId}, cultures={string.Join(",", cultureList)}. Exception: {ex}");
                return(null);
            }
            finally
            {
                _semaphore.ReleaseSafe();
            }

            var sport = GetSportForTournamentFromCache(tournamentId, cultureList, true);

            return(sport);
        }
        /// <summary>
        /// Asynchronously gets the <see cref="VariantDescriptionCacheItem"/> specified by it's id. If the item is not found in local cache, all items for specified
        /// language are fetched from the service and stored/merged into the local cache.
        /// </summary>
        /// <param name="id">The id of the <see cref="VariantDescriptionCacheItem"/> instance to get</param>
        /// <param name="cultures">A <see cref="IEnumerable{CultureInfo}"/> specifying the languages which the returned item must contain</param>
        /// <returns>A <see cref="Task"/> representing the async operation</returns>
        /// <exception cref="CommunicationException">An error occurred while accessing the remote party</exception>
        /// <exception cref="DeserializationException">An error occurred while deserializing fetched data</exception>
        /// <exception cref="FormatException">An error occurred while mapping deserialized entities</exception>
        private async Task <VariantDescriptionCacheItem> GetVariantDescriptionInternalAsync(string id, IEnumerable <CultureInfo> cultures)
        {
            Guard.Argument(cultures, nameof(cultures)).NotNull();//.NotEmpty();
            if (!cultures.Any())
            {
                throw new ArgumentOutOfRangeException(nameof(cultures));
            }

            var cultureList = cultures as List <CultureInfo> ?? cultures.ToList();

            VariantDescriptionCacheItem description;

            if ((description = GetItemFromCache(id)) != null && !LanguageHelper.GetMissingCultures(cultureList, description.FetchedLanguages).Any())
            {
                return(description);
            }
            try
            {
                await _semaphore.WaitAsync().ConfigureAwait(false);

                description = GetItemFromCache(id);
                var missingLanguages = LanguageHelper.GetMissingCultures(cultureList, description?.FetchedLanguages).ToList();

                if (missingLanguages.Any())
                {
                    // dont call for already fetched languages
                    missingLanguages = LanguageHelper.GetMissingCultures(missingLanguages, _fetchedLanguages).ToList();
                }

                if (!missingLanguages.Any())
                {
                    return(description);
                }

                var cultureTaskDictionary = missingLanguages.ToDictionary(l => l, l => _dataRouterManager.GetVariantDescriptionsAsync(l));
                await Task.WhenAll(cultureTaskDictionary.Values).ConfigureAwait(false);
            }
            catch (Exception ex)
            {
                var disposedException = ex as ObjectDisposedException;
                if (disposedException != null)
                {
                    ExecutionLog.Warn($"An error occurred while fetching market descriptions because the object graph is being disposed. Object causing the exception: {disposedException.ObjectName}.");
                    return(null);
                }
                throw;
            }
            finally
            {
                if (!_isDisposed)
                {
                    _semaphore.ReleaseSafe();
                }
            }

            return((description = GetItemFromCache(id)) != null && !LanguageHelper.GetMissingCultures(cultureList, description.FetchedLanguages).Any()
                ? description
                : null);
        }
예제 #4
0
        /// <summary>
        ///     Invoked when the <code>_timer</code> ticks in order to periodically fetch market descriptions for configured
        ///     languages
        /// </summary>
        /// <param name="sender">The <see cref="ITimer" /> raising the event</param>
        /// <param name="e">A <see cref="EventArgs" /> instance containing the event data</param>
        private async void OnTimerElapsed(object sender, EventArgs e)
        {
            if (_isDisposed)
            {
                return;
            }

            //when the timer first elapses fetch data only for languages which were not yet fetched. On subsequent timer elapses fetch data for all configured languages
            var languagesToFetch = _prefetchLanguages
                                   .Where(language => !_fetchedLanguages.Contains(language) || _hasTimerElapsedOnce).ToList();

            if (!languagesToFetch.Any())
            {
                _hasTimerElapsedOnce = true;
                return;
            }

            try
            {
                _fetchedLanguages.Clear();
                ExecutionLog.Debug(
                    $"Loading invariant market descriptions for [{string.Join(",", languagesToFetch.Select(l => l.TwoLetterISOLanguageName))}] (timer).");
                await GetMarketInternalAsync(0, languagesToFetch).ConfigureAwait(false);
            }
            catch (Exception ex)
            {
                if (ex is CommunicationException || ex is DeserializationException || ex is FormatException)
                {
                    var languagesString = string.Join(",", languagesToFetch.Select(l => l.TwoLetterISOLanguageName));
                    ExecutionLog.Warn(
                        $"An error occurred while periodically fetching market description of languages {languagesString}",
                        ex);
                    return;
                }

                var disposedException = ex as ObjectDisposedException;
                if (disposedException != null)
                {
                    ExecutionLog.Warn(
                        $"An error occurred while periodically fetching market descriptions because the object graph is being disposed. Object causing the exception:{disposedException.ObjectName}");
                    return;
                }

                if (ex is TaskCanceledException)
                {
                    ExecutionLog.Warn(
                        "An error occurred while periodically fetching market descriptions because the object graph is being disposed.");
                    return;
                }

                ExecutionLog.Warn("An error occurred while periodically fetching market description.", ex);
            }

            _hasTimerElapsedOnce = true;
        }
예제 #5
0
        /// <summary>
        /// Gets a <see cref="SportData"/> representing the sport specified by <code>id</code> in the languages specified by <code>cultures</code>, or a null reference
        /// if the specified sport does not exist, or it(or one of it's children) is not available in one of the requested languages
        /// </summary>
        /// <param name="id">A <see cref="URN"/> specifying the id of the sport to get</param>
        /// <param name="cultures">A <see cref="IEnumerable{CultrureInfo}"/> specifying the languages to which the sport must be translated</param>
        /// <returns>A <see cref="SportData"/> representing the requested sport translated into requested languages. </returns>
        private async Task <SportData> GetSportFromCacheAsync(URN id, IEnumerable <CultureInfo> cultures)
        {
            var cultureList = cultures as IList <CultureInfo> ?? cultures.ToList();

            await FetchSportCategoriesIfNeededAsync(id, cultureList).ConfigureAwait(false);

            List <CategoryData> categories = null;

            lock (_mergeLock)
            {
                SportCI cachedSport;
                if (!(Sports.TryGetValue(id, out cachedSport) && cachedSport.HasTranslationsFor(cultureList)))
                {
                    return(null);
                }

                try
                {
                    if (cachedSport.CategoryIds != null)
                    {
                        categories = new List <CategoryData>();
                        foreach (var categoryId in cachedSport.CategoryIds)
                        {
                            CategoryCI cachedCategory;
                            if (!(Categories.TryGetValue(categoryId, out cachedCategory) && cachedCategory.HasTranslationsFor(cultureList)))
                            {
                                ExecutionLog.Warn($"An error occurred while retrieving sport from cache.For sportId = {id} and lang =[{string.Join(",", cultureList)}] we are missing category {categoryId}.");
                                continue;
                            }

                            categories.Add(new CategoryData(
                                               cachedCategory.Id,
                                               cachedCategory.Name.Where(t => cultureList.Contains(t.Key)).ToDictionary(kvp => kvp.Key, kvp => kvp.Value),
                                               cachedCategory.CountryCode,
                                               cachedCategory.TournamentIds ?? new List <URN>()));
                        }
                    }
                }
                catch (Exception e)
                {
                    ExecutionLog.Warn($"An error occured while retrieving sport from cache. id={id} and lang=[{string.Join(",", cultureList)}].", e);
                }

                return(new SportData(
                           cachedSport.Id,
                           cachedSport.Name.Where(t => cultureList.Contains(t.Key)).ToDictionary(kvp => kvp.Key, kvp => kvp.Value),
                           categories));
            }
        }
        /// <summary>
        /// Merges the provided descriptions with those found in cache
        /// </summary>
        /// <param name="culture">A <see cref="CultureInfo"/> specifying the language of the <code>descriptions</code></param>
        /// <param name="descriptions">A <see cref="IEnumerable{MarketDescriptionDTO}"/> containing market descriptions in specified language</param>
        private void Merge(CultureInfo culture, IEnumerable <MarketDescriptionDTO> descriptions)
        {
            Guard.Argument(culture, nameof(culture)).NotNull();
            Guard.Argument(descriptions, nameof(descriptions)).NotNull();//.NotEmpty();
            if (!descriptions.Any())
            {
                throw new ArgumentOutOfRangeException(nameof(descriptions));
            }

            var descriptionList = descriptions as List <MarketDescriptionDTO> ?? descriptions.ToList();

            try
            {
                _semaphoreCacheMerge.Wait();
                foreach (var marketDescription in descriptionList)
                {
                    try
                    {
                        var cachedItem = _cache.GetCacheItem(marketDescription.Id.ToString());
                        if (cachedItem == null)
                        {
                            cachedItem = new CacheItem(marketDescription.Id.ToString(), MarketDescriptionCacheItem.Build(marketDescription, _mappingValidatorFactory, culture, CacheName));
                            _cache.Add(cachedItem, _cacheItemPolicy);
                        }
                        else
                        {
                            ((MarketDescriptionCacheItem)cachedItem.Value).Merge(marketDescription, culture);
                        }
                    }
                    catch (Exception e)
                    {
                        if (!(e is InvalidOperationException))
                        {
                            throw;
                        }

                        ExecutionLog.Warn($"Mapping validation for MarketDescriptionCacheItem failed. Id={marketDescription.Id}", e);
                    }
                }
                _fetchedLanguages.Add(culture);
            }
            finally
            {
                if (!_isDisposed)
                {
                    _semaphoreCacheMerge.Release();
                }
            }
        }
 /// <summary>
 /// Asynchronously loads the list of market descriptions from the Sports API
 /// </summary>
 /// <returns>Returns true if the action succeeded</returns>
 public async Task <bool> LoadMarketDescriptionsAsync()
 {
     try
     {
         ExecutionLog.Debug($"Loading variant market descriptions for [{string.Join(", ", _prefetchLanguages.Select(l => l.TwoLetterISOLanguageName))}] (user request).");
         _fetchedLanguages.Clear();
         await GetVariantDescriptionInternalAsync("0", _prefetchLanguages).ConfigureAwait(false);
     }
     catch (Exception ex)
     {
         ExecutionLog.Warn($"An error occurred while fetching market descriptions variant list. The exception:{ex.Message}");
         return(false);
     }
     return(true);
 }
예제 #8
0
        /// <summary>
        /// Asynchronously gets a <see cref="IEnumerable{SportData}"/> representing sport hierarchies for all sports supported by the feed.
        /// </summary>
        /// <param name="cultures">A <see cref="IEnumerable{CultureInfo}"/> specifying the languages in which the data is returned</param>
        /// <returns>A <see cref="Task{T}"/> representing the asynchronous operation</returns>
        public async Task <IEnumerable <SportData> > GetSportsAsync(IEnumerable <CultureInfo> cultures)
        {
            var cultureList = cultures as IList <CultureInfo> ?? cultures.ToList();

            //Just lock - don't even check if all the required data is available
            if (!await _semaphore.WaitAsyncSafe().ConfigureAwait(false))
            {
                return(null);
            }
            var missingCultures = cultureList.Where(c => !FetchedCultures.Contains(c)).ToList();

            try
            {
                // we have all available data - return the requested info
                if (!missingCultures.Any())
                {
                    var sports = Sports.Keys.Select(sportId =>
                    {
                        var sportFromCacheAsync = GetSportFromCacheAsync(sportId, cultureList);
                        sportFromCacheAsync.ConfigureAwait(false);
                        return(sportFromCacheAsync);
                    }).ToList();
                    return(await Task.WhenAll(sports).ConfigureAwait(false));
                }

                await FetchAndMergeAll(missingCultures, false).ConfigureAwait(false);

                return(await Task.WhenAll(Sports.Keys.Select(sportId =>
                {
                    var sportFromCacheAsync = GetSportFromCacheAsync(sportId, cultureList);
                    sportFromCacheAsync.ConfigureAwait(false);
                    return sportFromCacheAsync;
                }).ToList()));
            }
            catch (Exception ex)
            {
                ExecutionLog.Warn($"An exception occurred while attempting to fetch sports data for: {string.Join(",", missingCultures)}. Exception: {ex}");
                throw;
            }
            finally
            {
                _semaphore.ReleaseSafe();
            }
        }
예제 #9
0
        /// <summary>
        /// Fetches the data for pre-configured languages and merges it to internally used dictionaries. First time the method is invoked it fetches the data only for missing languages.
        /// On subsequent calls data for all configured languages is fetched and dictionary are cleared before fetched data is added / merged
        /// </summary>
        /// <param name="sender">A <see cref="ITimer"/> invoking the method</param>
        /// <param name="e">The <see cref="EventArgs"/> providing additional information about the event which invoked the method</param>
        private async void OnTimerElapsed(object sender, EventArgs e)
        {
            if (!await _semaphore.WaitAsyncSafe().ConfigureAwait(false))
            {
                return;
            }
            IList <CultureInfo> cultureInfos = new List <CultureInfo>();

            try
            {
                var missingLanguages = _wasDataAutoFetched
                    ? _requiredCultures
                    : _requiredCultures.Where(c => !FetchedCultures.Any()).ToList();

                cultureInfos = missingLanguages as IList <CultureInfo> ?? missingLanguages.ToList();
                if (cultureInfos.Any())
                {
                    await FetchAndMergeAll(cultureInfos, _wasDataAutoFetched).ConfigureAwait(false);

                    ExecutionLog.Info($"Sport data for languages [{string.Join(",", cultureInfos)}] successfully fetched and merged.");
                    _wasDataAutoFetched = true;
                }
            }
            catch (FeedSdkException ex)
            {
                ExecutionLog.Warn($"An exception occurred while attempting to fetch sport data for: {string.Join(",", cultureInfos)}. Exception was: {ex}");
            }
            catch (ObjectDisposedException)
            {
                ExecutionLog.Warn($"An exception occurred while attempting to fetch sport data for: {string.Join(",", cultureInfos)}. DataProvider was already disposed.");
            }
            catch (TaskCanceledException)
            {
                ExecutionLog.Warn($"An exception occurred while attempting to fetch sport data for: {string.Join(",", cultureInfos)}. Task canceled. DataProvider was already disposed.");
            }
            catch (Exception ex)
            {
                ExecutionLog.Warn($"An exception occurred while attempting to fetch sport data for: {string.Join(",", cultureInfos)}. Exception: {ex}");
            }
            finally
            {
                _semaphore.ReleaseSafe();
            }
        }
예제 #10
0
        /// <summary>
        ///     Merges the provided descriptions with those found in cache
        /// </summary>
        /// <param name="culture">A <see cref="CultureInfo" /> specifying the language of the <code>descriptions</code></param>
        /// <param name="descriptions">
        ///     A <see cref="IEnumerable{MarketDescriptionDTO}" /> containing market descriptions in
        ///     specified language
        /// </param>
        private void Merge(CultureInfo culture, IEnumerable <VariantDescriptionDTO> descriptions)
        {
            Contract.Requires(culture != null);
            Contract.Requires(descriptions != null && descriptions.Any());

            var descriptionList = descriptions as List <VariantDescriptionDTO> ?? descriptions.ToList();

            try
            {
                _semaphoreCacheMerge.Wait();
                foreach (var marketDescription in descriptionList)
                {
                    var cachedItem = _cache.GetCacheItem(marketDescription.Id);
                    if (cachedItem == null)
                    {
                        cachedItem = new CacheItem(marketDescription.Id,
                                                   VariantDescriptionCacheItem.Build(marketDescription, _mappingValidatorFactory, culture,
                                                                                     CacheName));
                        _cache.Add(cachedItem, new CacheItemPolicy());
                    }
                    else
                    {
                        ((VariantDescriptionCacheItem)cachedItem.Value).Merge(marketDescription, culture);
                    }
                }

                _fetchedLanguages.Add(culture);
            }
            catch (Exception e)
            {
                if (!(e is InvalidOperationException))
                {
                    throw;
                }
                ExecutionLog.Warn("Mapping validation for VariantDescriptionCacheItem failed.", e);
            }
            finally
            {
                if (!_isDisposed)
                {
                    _semaphoreCacheMerge.Release();
                }
            }
        }
예제 #11
0
        /// <summary>
        /// Asynchronously gets a <see cref="CategoryData"/> instance
        /// </summary>
        /// <param name="id">A <see cref="URN"/> specifying the id of the category</param>
        /// <param name="cultures">A <see cref="IEnumerable{CultureInfo}"/> specifying the languages in which the data is returned</param>
        /// <returns>A <see cref="Task{SportData}"/> representing the asynchronous operation</returns>
        public async Task <CategoryData> GetCategoryAsync(URN id, IEnumerable <CultureInfo> cultures)
        {
            Metric.Context("CACHE").Meter("SportDataCache->GetCategoryAsync", Unit.Calls).Mark();

            if (!await _semaphore.WaitAsyncSafe().ConfigureAwait(false))
            {
                return(null);
            }

            var        cultureList     = cultures as IList <CultureInfo> ?? cultures.ToList();
            var        missingCultures = cultureList;
            CategoryCI categoryCI;

            try
            {
                if (Categories.TryGetValue(id, out categoryCI))
                {
                    if (categoryCI.HasTranslationsFor(cultureList))
                    {
                        return(new CategoryData(id, categoryCI.Name.Where(t => cultureList.Contains(t.Key)).ToDictionary(kvp => kvp.Key, kvp => kvp.Value), categoryCI.CountryCode, categoryCI.TournamentIds));
                    }
                    missingCultures = cultureList.Where(c => !FetchedCultures.Contains(c)).ToList();
                }
                if (missingCultures.Any())
                {
                    await FetchAndMergeAll(missingCultures, false).ConfigureAwait(false);
                }
            }
            catch (Exception ex)
            {
                ExecutionLog.Warn($"An exception occurred while attempting to fetch category data for: id={id}, cultures={string.Join(",", cultureList)}. Exception: {ex}");
            }
            finally
            {
                _semaphore.ReleaseSafe();
            }

            return(Categories.TryGetValue(id, out categoryCI)
                ? new CategoryData(id, categoryCI.Name.Where(t => cultureList.Contains(t.Key)).ToDictionary(kvp => kvp.Key, kvp => kvp.Value), categoryCI.CountryCode, categoryCI.TournamentIds)
                : null);
        }
예제 #12
0
        /// <summary>
        ///     Merges the provided descriptions with those found in cache
        /// </summary>
        /// <param name="culture">A <see cref="CultureInfo" /> specifying the language of the <code>descriptions</code></param>
        /// <param name="description">A <see cref="MarketDescriptionDTO" /> containing market description in specified language</param>
        private void Merge(CultureInfo culture, MarketDescriptionDTO description)
        {
            Contract.Requires(culture != null);
            Contract.Requires(description != null);

            if (_isDisposed)
            {
                return;
            }

            try
            {
                _semaphoreCacheMerge.Wait();
                var cachedItem = _cache.GetCacheItem(GetCacheKey(description.Id, description.Variant));
                if (cachedItem == null)
                {
                    cachedItem = new CacheItem(GetCacheKey(description.Id, description.Variant),
                                               MarketDescriptionCacheItem.Build(description, _mappingValidatorFactory, culture, CacheName));
                    _cache.Add(cachedItem, _cacheItemPolicy);
                }
                else
                {
                    ((MarketDescriptionCacheItem)cachedItem.Value).Merge(description, culture);
                }
            }
            catch (Exception e)
            {
                if (!(e is InvalidOperationException))
                {
                    throw;
                }
                ExecutionLog.Warn("Mapping validation for MarketDescriptionCacheItem failed.", e);
            }
            finally
            {
                if (!_isDisposed)
                {
                    _semaphoreCacheMerge.Release();
                }
            }
        }
예제 #13
0
        /// <summary>
        ///     Invoked when the internally used timer elapses
        /// </summary>
        /// <param name="sender">A <see cref="object" /> representation of the <see cref="ITimer" /> raising the event</param>
        /// <param name="e">The <see cref="EventArgs" /> instance containing the event data</param>
        private async void OnTimerElapsed(object sender, EventArgs e)
        {
            //check what needs to be fetched, then go fetched by culture, (not by date)
            var datesToFetch = new List <DateTime>();

            lock (_addLock)
            {
                var date = DateTime.Now;
                for (var i = 0; i < 3; i++)
                {
                    if (_fetchedDates.Any(d => (date - d).TotalDays < 1))
                    {
                        continue;
                    }

                    datesToFetch.Add(date);
                    _fetchedDates.Add(date);
                    date = date.AddDays(1);
                }
            }

            if (!datesToFetch.Any())
            {
                return;
            }

            var culturesToFetch = _cultures.ToDictionary(ci => ci, ci => datesToFetch);

            foreach (var key in culturesToFetch)
            {
                try
                {
                    var tasks = key.Value.Select(d => GetScheduleAsync(d, key.Key)).ToList();
                    await Task.WhenAll(tasks).ConfigureAwait(false);
                }
                catch (ObjectDisposedException ex)
                {
                    ExecutionLog.Warn(
                        $"Periodic events schedule retrieval failed because the instance {ex.ObjectName} is being disposed.");
                }
            }
        /// <summary>
        /// Merges the provided descriptions with those found in cache
        /// </summary>
        /// <param name="culture">A <see cref="CultureInfo"/> specifying the language of the <code>descriptions</code></param>
        /// <param name="description">A <see cref="MarketDescriptionDTO"/> containing market description in specified language</param>
        private void Merge(CultureInfo culture, MarketDescriptionDTO description)
        {
            Guard.Argument(culture, nameof(culture)).NotNull();
            Guard.Argument(description, nameof(description)).NotNull();

            if (_isDisposed)
            {
                return;
            }

            try
            {
                _semaphoreCacheMerge.Wait();
                var cachedItem = _cache.GetCacheItem(GetCacheKey(description.Id, description.Variant));
                if (cachedItem == null)
                {
                    cachedItem = new CacheItem(GetCacheKey(description.Id, description.Variant), MarketDescriptionCacheItem.Build(description, _mappingValidatorFactory, culture, CacheName));
                    _cache.Add(cachedItem, new CacheItemPolicy {
                        SlidingExpiration = OperationManager.VariantMarketDescriptionCacheTimeout
                    });
                }
                else
                {
                    ((MarketDescriptionCacheItem)cachedItem.Value).Merge(description, culture);
                }
            }
            catch (Exception e)
            {
                if (!(e is InvalidOperationException))
                {
                    throw;
                }
                ExecutionLog.Warn("Mapping validation for MarketDescriptionCacheItem failed.", e);
            }
            finally
            {
                _semaphoreCacheMerge.ReleaseSafe();
            }
        }
        /// <summary>
        /// Deletes the item from cache
        /// </summary>
        /// <param name="id">A string representing the id of the item in the cache to be deleted</param>
        /// <param name="cacheItemType">A cache item type</param>
        public override void CacheDeleteItem(string id, CacheItemType cacheItemType)
        {
            if (cacheItemType == CacheItemType.All || cacheItemType == CacheItemType.MarketDescription)
            {
                try
                {
                    foreach (var fetchedVariant in _fetchedVariants)
                    {
                        if (fetchedVariant.Key.StartsWith(id))
                        {
                            DateTime date;
                            _fetchedVariants.TryRemove(id, out date);
                        }
                    }
                }
                catch (Exception e)
                {
                    ExecutionLog.Warn($"Error deleting fetchedVariants for {id}", e);
                }

                _cache.Remove(id);
            }
        }
예제 #16
0
        /// <summary>
        /// Adds the dto item to cache
        /// </summary>
        /// <param name="id">The identifier of the object</param>
        /// <param name="item">The item</param>
        /// <param name="culture">The culture</param>
        /// <param name="dtoType">Type of the dto</param>
        /// <param name="requester">The cache item which invoked request</param>
        /// <returns><c>true</c> if added, <c>false</c> otherwise</returns>
        protected override bool CacheAddDtoItem(URN id, object item, CultureInfo culture, DtoType dtoType, ISportEventCI requester)
        {
            //CacheLog.Debug($"Saving {id}.");
            if (_isDisposed)
            {
                return(false);
            }

            var saved = false;

            switch (dtoType)
            {
            case DtoType.MatchSummary:
                if (SaveCompetitorsFromSportEvent(item, culture))
                {
                    saved = true;
                }
                else
                {
                    LogSavingDtoConflict(id, typeof(MatchDTO), item.GetType());
                }
                break;

            case DtoType.RaceSummary:
                if (SaveCompetitorsFromSportEvent(item, culture))
                {
                    saved = true;
                }
                else
                {
                    LogSavingDtoConflict(id, typeof(StageDTO), item.GetType());
                }
                break;

            case DtoType.TournamentInfo:
                if (SaveCompetitorsFromSportEvent(item, culture))
                {
                    saved = true;
                }
                else
                {
                    LogSavingDtoConflict(id, typeof(TournamentInfoDTO), item.GetType());
                }
                break;

            case DtoType.SportEventSummary:
                if (SaveCompetitorsFromSportEvent(item, culture))
                {
                    saved = true;
                }
                else
                {
                    LogSavingDtoConflict(id, typeof(SportEventSummaryDTO), item.GetType());
                }
                break;

            case DtoType.Sport:
                break;

            case DtoType.Category:
                break;

            case DtoType.Tournament:
                break;

            case DtoType.PlayerProfile:
                var playerProfile = item as PlayerProfileDTO;
                if (playerProfile != null)
                {
                    AddPlayerProfile(playerProfile, null, culture, true);
                    saved = true;
                }
                else
                {
                    LogSavingDtoConflict(id, typeof(PlayerProfileDTO), item.GetType());
                }
                break;

            case DtoType.Competitor:
                var competitor = item as CompetitorDTO;
                if (competitor != null)
                {
                    AddCompetitor(id, competitor, culture, true);
                    saved = true;
                }
                else
                {
                    LogSavingDtoConflict(id, typeof(CompetitorDTO), item.GetType());
                }
                break;

            case DtoType.CompetitorProfile:
                var competitorProfile = item as CompetitorProfileDTO;
                if (competitorProfile != null)
                {
                    AddCompetitorProfile(id, competitorProfile, culture, true);
                    saved = true;
                }
                else
                {
                    LogSavingDtoConflict(id, typeof(CompetitorProfileDTO), item.GetType());
                }
                break;

            case DtoType.SimpleTeamProfile:
                var simpleTeamProfile = item as SimpleTeamProfileDTO;
                if (simpleTeamProfile != null)
                {
                    AddCompetitorProfile(id, simpleTeamProfile, culture, true);
                    saved = true;
                }
                else
                {
                    LogSavingDtoConflict(id, typeof(SimpleTeamProfileDTO), item.GetType());
                }
                break;

            case DtoType.MarketDescription:
                break;

            case DtoType.SportEventStatus:
                break;

            case DtoType.MatchTimeline:
                var matchTimeline = item as MatchTimelineDTO;
                if (matchTimeline != null)
                {
                    saved = SaveCompetitorsFromSportEvent(matchTimeline.SportEvent, culture);
                }
                else
                {
                    LogSavingDtoConflict(id, typeof(MatchTimelineDTO), item.GetType());
                }
                break;

            case DtoType.TournamentSeasons:
                break;

            case DtoType.Fixture:
                if (SaveCompetitorsFromSportEvent(item, culture))
                {
                    saved = true;
                }
                else
                {
                    LogSavingDtoConflict(id, typeof(FixtureDTO), item.GetType());
                }
                break;

            case DtoType.SportList:
                break;

            case DtoType.SportEventSummaryList:
                break;

            case DtoType.MarketDescriptionList:
                break;

            case DtoType.VariantDescription:
                break;

            case DtoType.VariantDescriptionList:
                break;

            case DtoType.Lottery:
                break;

            case DtoType.LotteryDraw:
                break;

            case DtoType.LotteryList:
                break;

            case DtoType.BookingStatus:
                break;

            case DtoType.SportCategories:
                break;

            default:
                ExecutionLog.Warn($"Trying to add unchecked dto type: {dtoType} for id: {id}.");
                break;
            }
            //CacheLog.Debug($"Saving {id} COMPLETED.");
            return(saved);
        }
        /// <summary>
        /// Adds the dto item to cache
        /// </summary>
        /// <param name="id">The identifier of the object</param>
        /// <param name="item">The item to be added</param>
        /// <param name="culture">The culture of the item</param>
        /// <param name="dtoType">Type of the dto</param>
        /// <param name="requester">The cache item which invoked request</param>
        /// <returns><c>true</c> if added, <c>false</c> otherwise</returns>
        /// <exception cref="System.ArgumentOutOfRangeException">dtoType - null</exception>
        protected override bool CacheAddDtoItem(URN id, object item, CultureInfo culture, DtoType dtoType, ISportEventCI requester)
        {
            if (_isDisposed)
            {
                return(false);
            }

            var saved = false;

            switch (dtoType)
            {
            case DtoType.Category:
                break;

            case DtoType.Competitor:
                break;

            case DtoType.CompetitorProfile:
                break;

            case DtoType.SimpleTeamProfile:
                break;

            case DtoType.Fixture:
                break;

            case DtoType.MarketDescription:
                var marketDescription = item as MarketDescriptionDTO;
                if (marketDescription != null)
                {
                    //WriteLog($"Saving {marketDescription.Id} variant description for lang: [{culture.TwoLetterISOLanguageName}].");
                    Merge(culture, marketDescription);
                    saved = true;
                    //WriteLog($"Saving {marketDescription.Id} variant description for lang: [{culture.TwoLetterISOLanguageName}] COMPLETED.");
                }
                else
                {
                    LogSavingDtoConflict(id, typeof(MarketDescriptionDTO), item.GetType(), ExecutionLog);
                }
                break;

            case DtoType.MarketDescriptionList:
                break;

            case DtoType.MatchSummary:
                break;

            case DtoType.MatchTimeline:
                break;

            case DtoType.PlayerProfile:
                break;

            case DtoType.RaceSummary:
                break;

            case DtoType.Sport:
                break;

            case DtoType.SportList:
                break;

            case DtoType.SportEventStatus:
                break;

            case DtoType.SportEventSummary:
                break;

            case DtoType.SportEventSummaryList:
                break;

            case DtoType.Tournament:
                break;

            case DtoType.TournamentInfo:
                break;

            case DtoType.TournamentSeasons:
                break;

            case DtoType.VariantDescription:
                break;

            case DtoType.VariantDescriptionList:
                break;

            case DtoType.Lottery:
                break;

            case DtoType.LotteryDraw:
                break;

            case DtoType.LotteryList:
                break;

            case DtoType.BookingStatus:
                break;

            case DtoType.SportCategories:
                break;

            case DtoType.AvailableSelections:
                break;

            default:
                ExecutionLog.Warn($"Trying to add unchecked dto type: {dtoType} for id: {id}.");
                break;
            }
            return(saved);
        }
예제 #18
0
        /// <summary>
        ///     Merges the provided descriptions with those found in cache
        /// </summary>
        /// <param name="culture">A <see cref="CultureInfo" /> specifying the language of the <code>descriptions</code></param>
        /// <param name="descriptions">
        ///     A <see cref="IEnumerable{MarketDescriptionDTO}" /> containing market descriptions in
        ///     specified language
        /// </param>
        private void Merge(CultureInfo culture, IEnumerable <MarketDescriptionDTO> descriptions)
        {
            Contract.Requires(culture != null);
            Contract.Requires(descriptions != null && descriptions.Any());

            var descriptionList = descriptions as List <MarketDescriptionDTO> ?? descriptions.ToList();

            try
            {
                _semaphoreCacheMerge.Wait();
                foreach (var marketDescription in descriptionList)
                {
                    try
                    {
                        var cachedItem = _cache.GetCacheItem(marketDescription.Id.ToString());
                        if (cachedItem == null)
                        {
                            cachedItem = new CacheItem(marketDescription.Id.ToString(),
                                                       MarketDescriptionCacheItem.Build(marketDescription, _mappingValidatorFactory, culture,
                                                                                        CacheName));
                            _cache.Add(cachedItem, _cacheItemPolicy);
                        }
                        else
                        {
                            ((MarketDescriptionCacheItem)cachedItem.Value).Merge(marketDescription, culture);
                        }
                    }
                    catch (Exception e)
                    {
                        if (!(e is InvalidOperationException))
                        {
                            throw;
                        }

                        ExecutionLog.Warn(
                            $"Mapping validation for MarketDescriptionCacheItem failed. Id={marketDescription.Id}", e);
                    }
                }

                _fetchedLanguages.Add(culture);
            }
            finally
            {
                if (!_isDisposed)
                {
                    _semaphoreCacheMerge.Release();
                }
            }

            //var c = _cache.Count();
            //ExecutionLog.Debug($"InvariantMarketDescriptionCache count: {c}.");
            //foreach (var keyValue in _cache.Where(s=>s.Key != null))
            //{
            //    var ci = (MarketDescriptionCacheItem)keyValue.Value;
            //    if (ci.Mappings != null)
            //    {
            //        foreach (var mapping in ci.Mappings)
            //        {
            //            if (mapping.OutcomeMappings != null)
            //            {
            //                foreach (var outcomeMapping in mapping.OutcomeMappings)
            //                {
            //                    if (outcomeMapping.ProducerOutcomeNames.Count != ci.FetchedLanguages.Count)
            //                    {
            //                        ExecutionLog.Error($"Market {ci.Id}: problem with outcome mapping {outcomeMapping.OutcomeId} and mapped marketId {outcomeMapping.MarketId}");
            //                    }
            //                }
            //            }
            //        }
            //    }
            //}
            //var cacheItem = _cache.First();
        }
예제 #19
0
        /// <summary>
        /// Gets a <see cref="SportData"/> representing the parent sport of the tournament specified by <code>tournamentId</code> in the languages specified by <code>cultures</code>, or a null reference
        /// if the specified sport does not exist, or it(or one of it's children) is not available in one of the requested languages
        /// </summary>
        /// <remarks>
        /// The returned <see cref="SportData"/> represents a sport with flattened hierarchy information - only one category and one tournament are found in the returned instance.
        /// </remarks>
        /// <param name="tournamentId">A <see cref="URN"/> specifying the tournament whose parent sport to get</param>
        /// <param name="cultures">A <see cref="IEnumerable{CultrureInfo}"/> specifying the languages to which the sport must be translated</param>
        /// <param name="fetchTournamentIfMissing">Indicates if the tournament should be fetched if not obtained via all tournaments request</param>
        /// <returns>A <see cref="SportData"/> representing the requested sport translated into requested languages</returns>
        private SportData GetSportForTournamentFromCache(URN tournamentId, IEnumerable <CultureInfo> cultures, bool fetchTournamentIfMissing)
        {
            var cultureList = cultures as IList <CultureInfo> ?? cultures.ToList();

            TournamentInfoCI cachedTournament = null;

            if (!_sportEventCache.CacheHasItem(tournamentId, CacheItemType.Tournament))
            {
                if (fetchTournamentIfMissing)
                {
                    try
                    {
                        cachedTournament = (TournamentInfoCI)_sportEventCache.GetEventCacheItem(tournamentId);
                        var unused = cachedTournament.GetCompetitorsAsync(cultureList).Result;
                    }
                    catch (Exception e)
                    {
                        ExecutionLog.Warn($"Error obtaining data for newly created tournament {tournamentId}.", e);
                        return(null);
                    }
                }
            }
            else
            {
                cachedTournament = (TournamentInfoCI)_sportEventCache.GetEventCacheItem(tournamentId);
                if (fetchTournamentIfMissing)
                {
                    try
                    {
                        var unused = cachedTournament.GetCompetitorsAsync(cultureList).Result;
                    }
                    catch (Exception e)
                    {
                        ExecutionLog.Warn($"Error obtaining data for newly created tournament {tournamentId}.", e);
                    }
                }
            }

            if (!(cachedTournament != null && cachedTournament.HasTranslationsFor(cultureList)))
            {
                return(null);
            }

            CategoryCI cachedCategory;

            if (!(Categories.TryGetValue(cachedTournament.GetCategoryIdAsync().Result, out cachedCategory) && cachedCategory.HasTranslationsFor(cultureList)))
            {
                return(null);
            }

            SportCI cachedSport;

            if (!(Sports.TryGetValue(cachedCategory.SportId, out cachedSport) && cachedSport.HasTranslationsFor(cultureList)))
            {
                return(null);
            }

            var category = new CategoryData(
                cachedCategory.Id,
                cachedCategory.Name.Where(k => cultureList.Contains(k.Key)).ToDictionary(kvp => kvp.Key, kvp => kvp.Value),
                cachedCategory.CountryCode,
                new[] { cachedTournament.Id });

            return(new SportData(
                       cachedSport.Id,
                       cachedSport.Name.Where(kvp => cultureList.Contains(kvp.Key)).ToDictionary(kvp => kvp.Key, kvp => kvp.Value),
                       new[] { category }));
        }
예제 #20
0
        /// <summary>
        ///     Asynchronously gets the <see cref="MarketDescriptionCacheItem" /> specified by it's id. If the item is not found in
        ///     local cache, all items for specified
        ///     language are fetched from the service and stored/merged into the local cache.
        /// </summary>
        /// <param name="id">The id of the <see cref="MarketDescriptionCacheItem" /> instance to get</param>
        /// <param name="cultures">
        ///     A <see cref="IEnumerable{CultureInfo}" /> specifying the languages which the returned item must
        ///     contain
        /// </param>
        /// <returns>A <see cref="Task" /> representing the async operation</returns>
        /// <exception cref="CommunicationException">An error occurred while accessing the remote party</exception>
        /// <exception cref="DeserializationException">An error occurred while deserializing fetched data</exception>
        /// <exception cref="FormatException">An error occurred while mapping deserialized entities</exception>
        private async Task <MarketDescriptionCacheItem> GetMarketInternalAsync(int id, IEnumerable <CultureInfo> cultures)
        {
            Contract.Requires(cultures != null && cultures.Any());

            var cultureList = cultures as List <CultureInfo> ?? cultures.ToList();

            MarketDescriptionCacheItem description;

            if ((description = GetItemFromCache(id)) != null &&
                !LanguageHelper.GetMissingCultures(cultureList, description.FetchedLanguages).Any())
            {
                return(description);
            }
            try
            {
                if (_isDisposed)
                {
                    return(null);
                }

                //WriteLog($"Prefetching invariant market description for id={id} and langs: [{string.Join(",", cultureList.Select(s => s.TwoLetterISOLanguageName))}].");
                await _semaphore.WaitAsync().ConfigureAwait(false);

                description = GetItemFromCache(id);
                var missingLanguages = LanguageHelper.GetMissingCultures(cultureList, description?.FetchedLanguages)
                                       .ToList();

                if (missingLanguages.Any())
                {
                    // dont call for already fetched languages
                    missingLanguages = LanguageHelper.GetMissingCultures(missingLanguages, _fetchedLanguages).ToList();
                }

                if (!missingLanguages.Any())
                {
                    return(description);
                }

                //WriteLog($"Actually fetching invariant market description for id={id} and langs:[{string.Join(",", missingLanguages.Select(s => s.TwoLetterISOLanguageName))}].");
                var cultureTaskDictionary =
                    missingLanguages.ToDictionary(l => l, l => _dataRouterManager.GetMarketDescriptionsAsync(l));
                await Task.WhenAll(cultureTaskDictionary.Values).ConfigureAwait(false);

                //WriteLog($"Actually fetching invariant market description for id={id} and langs:[{string.Join(",", missingLanguages.Select(s => s.TwoLetterISOLanguageName))}] COMPLETED.");

                //missingLanguages.ForEach(s => _fetchedLanguages.Add(s));
            }
            catch (Exception ex)
            {
                var disposedException = ex as ObjectDisposedException;
                if (disposedException != null)
                {
                    ExecutionLog.Warn(
                        $"An error occurred while fetching market descriptions because the object graph is being disposed. Object causing the exception: {disposedException.ObjectName}.");
                    return(null);
                }

                throw;
            }
            finally
            {
                if (!_isDisposed)
                {
                    _semaphore.Release();
                }
            }

            description = GetItemFromCache(id);

            return(description != null &&
                   !LanguageHelper.GetMissingCultures(cultureList, description.FetchedLanguages).Any()
                ? description
                : null);
        }
예제 #21
0
        /// <summary>
        /// Adds the item to the cache
        /// </summary>
        /// <param name="id">The identifier of the item</param>
        /// <param name="item">The item to be added</param>
        /// <param name="culture">The culture of the data-transfer-object</param>
        /// <param name="dtoType">Type of the dto item</param>
        /// <param name="requester">The cache item which invoked request</param>
        /// <returns><c>true</c> if is added/updated, <c>false</c> otherwise</returns>
        protected override bool CacheAddDtoItem(URN id, object item, CultureInfo culture, DtoType dtoType, ISportEventCI requester)
        {
            if (_isDisposed)
            {
                return(false);
            }

            var saved = false;

            switch (dtoType)
            {
            case DtoType.Category:
                var category = item as CategoryDTO;
                if (category != null)
                {
                    AddCategory(id, category, culture);
                    saved = true;
                }
                else
                {
                    LogSavingDtoConflict(id, typeof(CategoryDTO), item.GetType());
                }
                break;

            case DtoType.Competitor:
                break;

            case DtoType.CompetitorProfile:
                break;

            case DtoType.SimpleTeamProfile:
                break;

            case DtoType.Fixture:
                var fixture = item as FixtureDTO;
                if (fixture?.Tournament != null)
                {
                    AddSport(fixture.SportId, fixture.Tournament.Sport, culture);
                    AddCategory(fixture.Tournament.Category.Id, fixture.Tournament.Category, fixture.SportId, new List <URN> {
                        fixture.Tournament.Id
                    }, culture);
                }
                else
                {
                    LogSavingDtoConflict(id, typeof(FixtureDTO), item.GetType());
                }
                break;

            case DtoType.MarketDescription:
                break;

            case DtoType.MatchSummary:
                var match = item as MatchDTO;
                if (match?.Tournament != null)
                {
                    AddSport(match.SportId, match.Tournament.Sport, culture);
                    AddCategory(match.Tournament.Category.Id, match.Tournament.Category, match.SportId, new List <URN> {
                        match.Tournament.Id
                    }, culture);
                }
                else
                {
                    LogSavingDtoConflict(id, typeof(MatchDTO), item.GetType());
                }
                break;

            case DtoType.MatchTimeline:
                var timeline = item as MatchTimelineDTO;
                if (timeline?.SportEvent != null)
                {
                    AddDataFromSportEventSummary(timeline.SportEvent, culture);
                    saved = true;
                }
                else
                {
                    LogSavingDtoConflict(id, typeof(MatchTimelineDTO), item.GetType());
                }
                break;

            case DtoType.PlayerProfile:
                break;

            case DtoType.RaceSummary:
                var stageDTO = item as StageDTO;
                if (stageDTO != null)
                {
                    if (stageDTO.Status != null)
                    {
                        AddDataFromSportEventSummary(stageDTO, culture);
                    }
                    saved = true;
                }
                else
                {
                    LogSavingDtoConflict(id, typeof(StageDTO), item.GetType());
                }
                break;

            case DtoType.Sport:
                var sport = item as SportDTO;
                if (sport != null)
                {
                    AddSport(id, sport, culture);
                    saved = true;
                }
                else
                {
                    LogSavingDtoConflict(id, typeof(SportDTO), item.GetType());
                }
                break;

            case DtoType.SportList:
                var sportList = item as EntityList <SportDTO>;
                if (sportList != null)
                {
                    foreach (var s in sportList.Items)
                    {
                        AddSport(s.Id, s, culture);
                    }
                    saved = true;
                }
                else
                {
                    LogSavingDtoConflict(id, typeof(EntityList <SportDTO>), item.GetType());
                }
                break;

            case DtoType.SportEventStatus:
                break;

            case DtoType.SportEventSummary:
                var summary = item as SportEventSummaryDTO;
                if (summary != null)
                {
                    AddDataFromSportEventSummary(summary, culture);
                    saved = true;
                }
                else
                {
                    LogSavingDtoConflict(id, typeof(SportEventSummaryDTO), item.GetType());
                }
                break;

            case DtoType.SportEventSummaryList:
                var summaryList = item as EntityList <SportEventSummaryDTO>;
                if (summaryList != null)
                {
                    foreach (var s in summaryList.Items)
                    {
                        AddDataFromSportEventSummary(s, culture);
                    }
                    saved = true;
                }
                else
                {
                    LogSavingDtoConflict(id, typeof(EntityList <SportEventSummaryDTO>), item.GetType());
                }
                break;

            case DtoType.Tournament:
                var tour = item as TournamentDTO;
                if (tour != null)
                {
                    AddSport(tour.Sport.Id, tour.Sport, culture);
                    AddCategory(tour.Category.Id, tour.Category, tour.Sport.Id, new List <URN> {
                        tour.Id
                    }, culture);
                }
                else
                {
                    LogSavingDtoConflict(id, typeof(SportDTO), item.GetType());
                }
                break;

            case DtoType.TournamentInfo:
                var tourInfo = item as TournamentInfoDTO;
                if (tourInfo != null)
                {
                    AddSport(tourInfo.SportId, tourInfo.Sport, culture);
                    AddCategory(tourInfo.Category.Id, tourInfo.Category, tourInfo.Sport.Id, new List <URN> {
                        tourInfo.Id
                    }, culture);
                }
                else
                {
                    LogSavingDtoConflict(id, typeof(SportDTO), item.GetType());
                }
                break;

            case DtoType.TournamentSeasons:
                var tourSeasons = item as TournamentSeasonsDTO;
                if (tourSeasons?.Tournament != null)
                {
                    var tourSeasonsTournament = tourSeasons.Tournament;
                    AddSport(tourSeasonsTournament.SportId, tourSeasonsTournament.Sport, culture);
                    AddCategory(tourSeasonsTournament.Category.Id, tourSeasonsTournament.Category, tourSeasonsTournament.Sport.Id, new List <URN> {
                        tourSeasonsTournament.Id
                    }, culture);
                    saved = true;
                }
                else
                {
                    LogSavingDtoConflict(id, typeof(TournamentInfoDTO), item.GetType());
                }
                break;

            case DtoType.MarketDescriptionList:
                break;

            case DtoType.VariantDescription:
                break;

            case DtoType.VariantDescriptionList:
                break;

            case DtoType.Lottery:
                var lottery = item as LotteryDTO;
                if (lottery != null)
                {
                    AddDataFromSportEventSummary(lottery, culture);
                    //if (lottery.DrawEvents == null || !lottery.DrawEvents.Any())
                    //{
                    //    _dataRouterManager.GetLotteryScheduleAsync(lottery.Id, culture);
                    //}
                    //else
                    //{
                    //    _dataRouterManager.GetDrawFixtureAsync(lottery.DrawEvents.First().Id, culture);
                    //}
                    saved = true;
                }
                else
                {
                    LogSavingDtoConflict(id, typeof(LotteryDTO), item.GetType());
                }
                break;

            case DtoType.LotteryDraw:
                var lotteryDraw = item as DrawDTO;
                if (lotteryDraw != null)
                {
                    AddDataFromSportEventSummary(lotteryDraw, culture);
                    saved = true;
                }
                else
                {
                    LogSavingDtoConflict(id, typeof(DrawDTO), item.GetType());
                }
                break;

            case DtoType.LotteryList:
                var lotteryList = item as EntityList <LotteryDTO>;
                if (lotteryList != null)
                {
                    foreach (var s in lotteryList.Items)
                    {
                        AddDataFromSportEventSummary(s, culture);
                    }
                    saved = true;
                }
                else
                {
                    LogSavingDtoConflict(id, typeof(EntityList <LotteryDTO>), item.GetType());
                }
                break;

            case DtoType.SportCategories:
                var sportCategories = item as SportCategoriesDTO;
                if (sportCategories != null)
                {
                    AddSport(sportCategories.Sport.Id, sportCategories, culture);
                    AddCategories(sportCategories, culture);
                }
                else
                {
                    LogSavingDtoConflict(id, typeof(SportCategoriesDTO), item.GetType());
                }
                break;

            case DtoType.BookingStatus:
                break;

            case DtoType.AvailableSelections:
                break;

            default:
                ExecutionLog.Warn($"Trying to add unchecked dto type: {dtoType} for id: {id}.");
                break;
            }

            return(saved);
        }
예제 #22
0
        /// <summary>
        ///     Adds the dto item to cache
        /// </summary>
        /// <param name="id">The identifier of the object</param>
        /// <param name="item">The item</param>
        /// <param name="culture">The culture</param>
        /// <param name="dtoType">Type of the dto</param>
        /// <param name="requester">The cache item which invoked request</param>
        /// <returns><c>true</c> if added, <c>false</c> otherwise</returns>
        protected override bool CacheAddDtoItem(URN id, object item, CultureInfo culture, DtoType dtoType,
                                                ISportEventCI requester)
        {
            if (_isDisposed)
            {
                return(false);
            }

            var saved = false;

            switch (dtoType)
            {
            case DtoType.Category:
                break;

            case DtoType.Competitor:
                break;

            case DtoType.CompetitorProfile:
                break;

            case DtoType.SimpleTeamProfile:
                break;

            case DtoType.Fixture:
                var fixtureDTO = item as FixtureDTO;
                if (fixtureDTO != null)
                {
                    if (fixtureDTO.Status != null)
                    {
                        AddSportEventStatus(id, new SportEventStatusCI(null, fixtureDTO.Status), "Fixture");
                    }
                    saved = true;
                }
                else
                {
                    LogSavingDtoConflict(id, typeof(FixtureDTO), item.GetType());
                }

                break;

            case DtoType.MarketDescription:
                break;

            case DtoType.MatchSummary:
                var matchDTO = item as MatchDTO;
                if (matchDTO != null)
                {
                    if (matchDTO.Status != null)
                    {
                        AddSportEventStatus(id, new SportEventStatusCI(null, matchDTO.Status), "Match");
                    }
                    saved = true;
                }
                else
                {
                    LogSavingDtoConflict(id, typeof(MatchDTO), item.GetType());
                }

                break;

            case DtoType.MatchTimeline:
                var matchTimelineDTO = item as MatchTimelineDTO;
                if (matchTimelineDTO != null)
                {
                    if (matchTimelineDTO.SportEventStatus != null)
                    {
                        AddSportEventStatus(id, new SportEventStatusCI(null, matchTimelineDTO.SportEventStatus),
                                            "MatchTimeline");
                    }
                    saved = true;
                }
                else
                {
                    LogSavingDtoConflict(id, typeof(MatchTimelineDTO), item.GetType());
                }

                break;

            case DtoType.PlayerProfile:
                break;

            case DtoType.RaceSummary:
                var stageDTO = item as StageDTO;
                if (stageDTO != null)
                {
                    if (stageDTO.Status != null)
                    {
                        AddSportEventStatus(id, new SportEventStatusCI(null, stageDTO.Status), "Stage");
                    }
                    saved = true;
                }
                else
                {
                    LogSavingDtoConflict(id, typeof(StageDTO), item.GetType());
                }

                break;

            case DtoType.Sport:
                break;

            case DtoType.SportList:
                break;

            case DtoType.SportEventStatus:
                var sportEventStatusDTO = item as SportEventStatusDTO;
                if (sportEventStatusDTO != null)
                {
                    AddSportEventStatus(id, new SportEventStatusCI(sportEventStatusDTO, null), "OddsChange");
                    saved = true;
                }
                else
                {
                    LogSavingDtoConflict(id, typeof(SportEventStatusDTO), item.GetType());
                }

                break;

            case DtoType.SportEventSummary:
                var competitionDTO = item as CompetitionDTO;
                if (competitionDTO != null)
                {
                    if (competitionDTO.Status != null)
                    {
                        AddSportEventStatus(id, new SportEventStatusCI(null, competitionDTO.Status),
                                            "SportEventSummary");
                    }
                    saved = true;
                }

                break;

            case DtoType.SportEventSummaryList:
                var summaryList = item as EntityList <SportEventSummaryDTO>;
                if (summaryList != null)
                {
                    foreach (var s in summaryList.Items)
                    {
                        var compDTO = s as CompetitionDTO;
                        if (compDTO?.Status != null)
                        {
                            AddSportEventStatus(id, new SportEventStatusCI(null, compDTO.Status),
                                                "SportEventSummaryList");
                        }
                    }

                    saved = true;
                }
                else
                {
                    LogSavingDtoConflict(id, typeof(EntityList <SportEventSummaryDTO>), item.GetType());
                }

                break;

            case DtoType.Tournament:
                break;

            case DtoType.TournamentInfo:
                break;

            case DtoType.TournamentSeasons:
                break;

            case DtoType.MarketDescriptionList:
                break;

            case DtoType.VariantDescription:
                break;

            case DtoType.VariantDescriptionList:
                break;

            case DtoType.Lottery:
                break;

            case DtoType.LotteryDraw:
                break;

            case DtoType.LotteryList:
                break;

            case DtoType.BookingStatus:
                break;

            case DtoType.SportCategories:
                break;

            default:
                ExecutionLog.Warn($"Trying to add unchecked dto type: {dtoType} for id: {id}.");
                break;
            }

            //CacheLog.Debug($"Saving {id} COMPLETED. Saved={saved}.");
            return(saved);
        }
예제 #23
0
        /// <summary>
        /// Adds the item to the cache
        /// </summary>
        /// <param name="id">The identifier of the item</param>
        /// <param name="item">The item to be add</param>
        /// <param name="culture">The culture of the data-transfer-object</param>
        /// <param name="dtoType">Type of the cache item</param>
        /// <param name="requester">The cache item which invoked request</param>
        /// <returns><c>true</c> if is added/updated, <c>false</c> otherwise</returns>
        /// <exception cref="NotImplementedException"></exception>
        protected override bool CacheAddDtoItem(URN id, object item, CultureInfo culture, DtoType dtoType, ISportEventCI requester)
        {
            if (_isDisposed)
            {
                return(false);
            }

            var saved = false;

            switch (dtoType)
            {
            case DtoType.Category:
                break;

            case DtoType.Competitor:
                break;

            case DtoType.CompetitorProfile:
                break;

            case DtoType.SimpleTeamProfile:
                break;

            case DtoType.Fixture:
                var fixture = item as FixtureDTO;
                if (fixture != null)
                {
                    AddSportEvent(id, fixture, culture, requester, dtoType);
                    saved = true;
                }
                else
                {
                    LogSavingDtoConflict(id, typeof(FixtureDTO), item.GetType());
                }
                break;

            case DtoType.MarketDescription:
                break;

            case DtoType.MatchSummary:
                var match = item as MatchDTO;
                if (match != null)
                {
                    AddSportEvent(id, match, culture, requester, dtoType);
                    if (match.Tournament != null)
                    {
                        var ti = new TournamentInfoDTO(match.Tournament);
                        AddSportEvent(ti.Id, ti, culture, requester, dtoType);
                    }
                    saved = true;
                }
                else
                {
                    LogSavingDtoConflict(id, typeof(MatchDTO), item.GetType());
                }
                break;

            case DtoType.MatchTimeline:
                var timeline = item as MatchTimelineDTO;
                if (timeline != null)
                {
                    AddMatchTimeLine(timeline, culture, requester, dtoType);
                    saved = true;
                }
                else
                {
                    LogSavingDtoConflict(id, typeof(MatchTimelineDTO), item.GetType());
                }
                break;

            case DtoType.PlayerProfile:
                break;

            case DtoType.RaceSummary:
                var stage = item as StageDTO;
                if (stage != null)
                {
                    AddSportEvent(id, stage, culture, requester, dtoType);
                    if (stage.Tournament != null)
                    {
                        var ti = new TournamentInfoDTO(stage.Tournament);
                        AddSportEvent(ti.Id, ti, culture, requester, dtoType);
                    }
                    saved = true;
                }
                else
                {
                    LogSavingDtoConflict(id, typeof(StageDTO), item.GetType());
                }
                break;

            case DtoType.Sport:
                var sport = item as SportDTO;
                if (sport != null)
                {
                    SaveTournamentDataFromSport(sport, culture);
                    saved = true;
                }
                else
                {
                    LogSavingDtoConflict(id, typeof(SportDTO), item.GetType());
                }
                break;

            case DtoType.SportList:
                var sportEntityList = item as EntityList <SportDTO>;
                if (sportEntityList != null)
                {
                    foreach (var sportDTO in sportEntityList.Items)
                    {
                        SaveTournamentDataFromSport(sportDTO, culture);
                    }
                    saved = true;
                }
                else
                {
                    LogSavingDtoConflict(id, typeof(EntityList <SportDTO>), item.GetType());
                }
                break;

            case DtoType.SportEventStatus:
                break;

            case DtoType.SportEventSummary:
                var tourInfo = item as TournamentInfoDTO;
                if (tourInfo != null)
                {
                    SaveTournamentDataToSportEventCache(tourInfo, tourInfo.CurrentSeason?.Id, culture);
                    if (tourInfo.Season != null)
                    {
                        SaveTournamentDataToSportEventCache(tourInfo, tourInfo.Season?.Id, culture);
                    }
                    break;
                }
                var summary = item as SportEventSummaryDTO;
                if (summary != null)
                {
                    AddSportEvent(id, summary, culture, requester, dtoType);
                    saved = true;
                }
                else
                {
                    LogSavingDtoConflict(id, typeof(SportEventSummaryDTO), item.GetType());
                }
                break;

            case DtoType.SportEventSummaryList:
                var summaryList = item as EntityList <SportEventSummaryDTO>;
                if (summaryList != null)
                {
                    foreach (var s in summaryList.Items)
                    {
                        var tourInfosDTO = s as TournamentInfoDTO;
                        if (tourInfosDTO != null)
                        {
                            SaveTournamentDataToSportEventCache(tourInfosDTO, tourInfosDTO.CurrentSeason?.Id, culture);
                            if (tourInfosDTO.Season != null)
                            {
                                SaveTournamentDataToSportEventCache(tourInfosDTO, tourInfosDTO.Season?.Id, culture);
                            }
                            continue;
                        }
                        AddSportEvent(s.Id, s, culture, requester, dtoType);
                    }
                    saved = true;
                }
                else
                {
                    LogSavingDtoConflict(id, typeof(EntityList <SportEventSummaryDTO>), item.GetType());
                }
                break;

            case DtoType.Tournament:
                var t = item as TournamentDTO;
                if (t != null)
                {
                    var ti = new TournamentInfoDTO(t);
                    AddSportEvent(id, ti, culture, requester, dtoType);
                    saved = true;
                }
                else
                {
                    LogSavingDtoConflict(id, typeof(TournamentDTO), item.GetType());
                }
                break;

            case DtoType.TournamentInfo:
                var tour = item as TournamentInfoDTO;
                if (tour != null)
                {
                    AddSportEvent(id, tour, culture, requester, dtoType);
                    saved = true;
                }
                else
                {
                    LogSavingDtoConflict(id, typeof(TournamentInfoDTO), item.GetType());
                }
                break;

            case DtoType.TournamentSeasons:
                var tourSeasons = item as TournamentSeasonsDTO;
                if (tourSeasons?.Tournament != null)
                {
                    AddSportEvent(id, tourSeasons.Tournament, culture, requester, dtoType);
                    var cacheItem = (TournamentInfoCI)_sportEventCacheItemFactory.Get(Cache.Get(id.ToString()));
                    cacheItem.Merge(tourSeasons, culture, true);

                    if (tourSeasons.Seasons != null && tourSeasons.Seasons.Any())
                    {
                        foreach (var season in tourSeasons.Seasons)
                        {
                            AddSportEvent(season.Id, new TournamentInfoDTO(season), culture, null, dtoType);
                        }
                    }
                    saved = true;
                }
                else
                {
                    LogSavingDtoConflict(id, typeof(TournamentInfoDTO), item.GetType());
                }
                break;

            case DtoType.MarketDescriptionList:
                break;

            case DtoType.VariantDescription:
                break;

            case DtoType.VariantDescriptionList:
                break;

            case DtoType.Lottery:
                var lottery = item as LotteryDTO;
                if (lottery != null)
                {
                    AddSportEvent(id, lottery, culture, requester, dtoType);
                    saved = true;
                }
                else
                {
                    LogSavingDtoConflict(id, typeof(TournamentInfoDTO), item.GetType());
                }
                break;

            case DtoType.LotteryDraw:
                var draw = item as DrawDTO;
                if (draw != null)
                {
                    AddSportEvent(id, draw, culture, requester, dtoType);
                    saved = true;
                }
                else
                {
                    LogSavingDtoConflict(id, typeof(TournamentInfoDTO), item.GetType());
                }
                break;

            case DtoType.LotteryList:
                var lotteryList = item as EntityList <LotteryDTO>;
                if (lotteryList != null && lotteryList.Items.Any())
                {
                    foreach (var l in lotteryList.Items)
                    {
                        AddSportEvent(l.Id, l, culture, requester, dtoType);
                    }
                    saved = true;
                }
                else
                {
                    LogSavingDtoConflict(id, typeof(TournamentInfoDTO), item.GetType());
                }
                break;

            case DtoType.BookingStatus:
                if (Cache.Contains(id.ToString()))
                {
                    var e    = Cache.Get(id.ToString());
                    var comp = e as CompetitionCI;
                    comp?.Book();
                }
                break;

            case DtoType.SportCategories:
                break;

            default:
                ExecutionLog.Warn($"Trying to add unchecked dto type:{dtoType} for id: {id}.");
                break;
            }
            return(saved);
        }
예제 #24
0
        /// <summary>
        /// Invoked when the internally used timer elapses
        /// </summary>
        /// <param name="sender">A <see cref="object"/> representation of the <see cref="ITimer"/> raising the event</param>
        /// <param name="e">The <see cref="EventArgs"/> instance containing the event data</param>
        private async void OnTimerElapsed(object sender, EventArgs e)
        {
            //check what needs to be fetched, then go fetched by culture, (not by date)
            var datesToFetch = new List <DateTime>();

            lock (_addLock)
            {
                var date = DateTime.Now;
                for (var i = 0; i < 3; i++)
                {
                    if (_fetchedDates.Any(d => (date - d).TotalDays < 1))
                    {
                        continue;
                    }

                    datesToFetch.Add(date);
                    _fetchedDates.Add(date);
                    date = date.AddDays(1);
                }
            }

            if (!datesToFetch.Any())
            {
                return;
            }

            var culturesToFetch = _cultures.ToDictionary(ci => ci, ci => datesToFetch);

            foreach (var key in culturesToFetch)
            {
                try
                {
                    var tasks = key.Value.Select(d => GetScheduleAsync(d, key.Key)).ToList();
                    await Task.WhenAll(tasks).ConfigureAwait(false);
                }
                catch (ObjectDisposedException ex)
                {
                    ExecutionLog.Warn($"Periodic events schedule retrieval failed because the instance {ex.ObjectName} is being disposed.");
                }
                catch (TaskCanceledException)
                {
                    ExecutionLog.Warn("Periodic events schedule retrieval failed because the instance is being disposed.");
                }
                catch (FeedSdkException ex)
                {
                    ExecutionLog.Warn($"An exception occurred while attempting to retrieve schedule. Exception was: {ex}");
                }
                catch (AggregateException ex)
                {
                    var baseException = ex.GetBaseException();
                    if (baseException.GetType() == typeof(ObjectDisposedException))
                    {
                        ExecutionLog.Warn($"Error happened during fetching schedule, because the instance {((ObjectDisposedException) baseException).ObjectName} is being disposed.");
                    }
                }
                catch (Exception ex)
                {
                    ExecutionLog.Warn($"An exception occurred while attempting to retrieve schedule. Exception: {ex}");
                }
            }
        }