Example #1
0
        /// <summary>
        /// Asynchronously gets a <see cref="IEnumerable{T}"/> representing competitors in the sport event associated with the current instance
        /// </summary>
        /// <returns>A <see cref="Task{T}"/> representing the retrieval operation</returns>
        public async Task <IEnumerable <ICompetitor> > GetCompetitorsAsync()
        {
            var competitionCI = (CompetitionCI)SportEventCache.GetEventCacheItem(Id);

            if (competitionCI == null)
            {
                ExecutionLog.Debug($"Missing data. No sportEvent cache item for id={Id}.");
                return(null);
            }
            var items = ExceptionStrategy == ExceptionHandlingStrategy.THROW
                ? await competitionCI.GetCompetitorsIdsAsync(Cultures).ConfigureAwait(false)
                : await new Func <IEnumerable <CultureInfo>, Task <IEnumerable <URN> > >(competitionCI.GetCompetitorsIdsAsync).SafeInvokeAsync(Cultures, ExecutionLog, GetFetchErrorMessage("CompetitorsIds")).ConfigureAwait(false);

            var competitorsIds = items == null ? new List <URN>() : items.ToList();

            if (!competitorsIds.Any())
            {
                return(new List <ICompetitor>());
            }

            var tasks = competitorsIds.Select(s => _sportEntityFactory.BuildTeamCompetitorAsync(s, Cultures, competitionCI, ExceptionStrategy)).ToList();
            await Task.WhenAll(tasks).ConfigureAwait(false);

            return(tasks.Select(s => s.Result));
        }
Example #2
0
        /// <summary>
        /// Asynchronously gets a <see cref="ITeamCompetitor" /> representing away competitor of the match associated with the current instance
        /// </summary>
        /// <returns>A <see cref="Task{ITeamCompetitor}"/> representing the retrieval operation</returns>
        public async Task<ITeamCompetitor> GetAwayCompetitorAsync()
        {
            var matchCI = (IMatchCI)SportEventCache.GetEventCacheItem(Id);
            if (matchCI == null)
            {
                ExecutionLog.Debug($"Missing data. No match cache item for id={Id}.");
                return null;
            }
            var items = ExceptionStrategy == ExceptionHandlingStrategy.THROW
                ? await matchCI.GetCompetitorsIdsAsync(Cultures).ConfigureAwait(false)
                : await new Func<IEnumerable<CultureInfo>, Task<IEnumerable<URN>>>(matchCI.GetCompetitorsIdsAsync).SafeInvokeAsync(Cultures, ExecutionLog, GetFetchErrorMessage("CompetitorsIds")).ConfigureAwait(false);

            if (items == null)
            {
                return null;
            }

            var competitorUrns = items.ToList();
            if (competitorUrns.Count == 2)
            {
                return await _sportEntityFactory.BuildTeamCompetitorAsync(competitorUrns[1], Cultures, matchCI, ExceptionStrategy).ConfigureAwait(false);
            }

            ExecutionLog.Error($"Received {competitorUrns.Count} competitors for match[Id = {Id}]. Match can have only 2 competitors.");
            throw new InvalidOperationException($"Invalid number of competitors. Match must have exactly 2 competitors, received {competitorUrns.Count}");
        }
Example #3
0
        /// <summary>
        /// Asynchronously gets the associated category
        /// </summary>
        /// <returns>The associated category</returns>
        public async Task <ICategorySummary> GetCategoryAsync()
        {
            var lotteryCI = (LotteryCI)SportEventCache.GetEventCacheItem(Id);

            if (lotteryCI == null)
            {
                ExecutionLog.Debug($"Missing data. No lottery cache item for id={Id}.");
                return(null);
            }

            var categoryId = ExceptionStrategy == ExceptionHandlingStrategy.THROW
                ? await lotteryCI.GetCategoryIdAsync().ConfigureAwait(false)
                : await new Func <Task <URN> >(lotteryCI.GetCategoryIdAsync).SafeInvokeAsync(ExecutionLog, GetFetchErrorMessage("CategoryId")).ConfigureAwait(false);

            if (categoryId == null)
            {
                ExecutionLog.Debug($"Missing data. No categoryId for lottery cache item with id={Id}.");
                return(null);
            }
            var categoryData = ExceptionStrategy == ExceptionHandlingStrategy.THROW
                ? await _sportDataCache.GetCategoryAsync(categoryId, Cultures).ConfigureAwait(false)
                : await new Func <URN, IEnumerable <CultureInfo>, Task <CategoryData> >(_sportDataCache.GetCategoryAsync).SafeInvokeAsync(categoryId, Cultures, ExecutionLog, GetFetchErrorMessage("CategoryData")).ConfigureAwait(false);

            return(categoryData == null
                ? null
                : new CategorySummary(categoryData.Id, categoryData.Names, categoryData.CountryCode));
        }
Example #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;
        }
Example #5
0
        public async Task <StageType> GetStageTypeAsync()
        {
            var stageCI = (StageCI)SportEventCache.GetEventCacheItem(Id);

            if (stageCI == null)
            {
                ExecutionLog.Debug($"Missing data. No stage cache item for id={Id}.");
                return(StageType.Child);
            }
            return(await stageCI.GetTypeAsync().ConfigureAwait(false));
        }
        /// <summary>
        /// Adds the sport event status to the internal cache
        /// </summary>
        /// <param name="eventId">The eventId of the sport event status to be cached</param>
        /// <param name="sportEventStatus">The sport event status to be cached</param>
        /// <param name="statusOnEvent">The sport event status received directly on event level</param>
        /// <param name="source">The source of the SES</param>
        // ReSharper disable once UnusedParameter.Local
        private void AddSportEventStatus(URN eventId, SportEventStatusCI sportEventStatus, string statusOnEvent, string source)
        {
            if (_isDisposed)
            {
                return;
            }

            if (sportEventStatus == null)
            {
                return;
            }

            Guard.Argument(eventId, nameof(eventId)).NotNull();


            if (string.IsNullOrEmpty(source) ||
                source.Equals("OddsChange", StringComparison.InvariantCultureIgnoreCase) ||
                source.Equals("SportEventSummary", StringComparison.InvariantCultureIgnoreCase) ||
                !_sportEventStatusCache.Contains(eventId.ToString()))
            {
                lock (_lock)
                {
                    if (!string.IsNullOrEmpty(source))
                    {
                        if (OperationManager.IgnoreBetPalTimelineSportEventStatus && source.Contains("Timeline") && _ignoreEventsTimelineCache.Contains(eventId.ToString()))
                        {
                            ExecutionLog.Debug($"Received SES for {eventId} from {source} with EventStatus:{sportEventStatus.Status} (timeline ignored)");
                            return;
                        }

                        source = $" from {source}";
                    }

                    ExecutionLog.Debug($"Received SES for {eventId}{source} with EventStatus:{sportEventStatus.Status}");
                    var cacheItem = _sportEventStatusCache.AddOrGetExisting(eventId.ToString(),
                                                                            sportEventStatus,
                                                                            new CacheItemPolicy
                    {
                        AbsoluteExpiration =
                            DateTimeOffset.Now.AddSeconds(OperationManager.SportEventStatusCacheTimeout.TotalSeconds)
                    })
                                    as SportEventStatusCI;
                    if (cacheItem != null)
                    {
                        cacheItem.SetFeedStatus(sportEventStatus.FeedStatusDTO);
                        cacheItem.SetSapiStatus(sportEventStatus.SapiStatusDTO);
                    }
                }
            }
            else
            {
                ExecutionLog.Debug($"Received SES for {eventId} from {source} with EventStatus:{sportEventStatus.Status} (ignored)");
            }
        }
 /// <summary>
 /// Asynchronously gets a <see cref="BookingStatus"/> enum member providing booking status for the associated @event or a null reference if booking status is not known
 /// </summary>
 /// <returns></returns>
 public async Task<BookingStatus?> GetBookingStatusAsync()
 {
     var competitionCI = (CompetitionCI)SportEventCache.GetEventCacheItem(Id);
     if (competitionCI == null)
     {
         ExecutionLog.Debug($"Missing data. No sportEvent cache item for id={Id}.");
         return null;
     }
     return ExceptionStrategy == ExceptionHandlingStrategy.THROW
         ? await competitionCI.GetBookingStatusAsync().ConfigureAwait(false)
         : await new Func<Task<BookingStatus?>>(competitionCI.GetBookingStatusAsync).SafeInvokeAsync(ExecutionLog, GetFetchErrorMessage("BookingStatus")).ConfigureAwait(false);
 }
Example #8
0
 /// <summary>
 /// Asynchronously gets a <see cref="IFixture"/> instance containing information about the arranged sport event
 /// </summary>
 /// <returns>A <see cref="Task{IFixture}"/> representing the retrieval operation</returns>
 /// <remarks>A Fixture is a sport event that has been arranged for a particular time and place</remarks>
 public async Task<IFixture> GetFixtureAsync()
 {
     var matchCI = (IMatchCI)SportEventCache.GetEventCacheItem(Id);
     if (matchCI == null)
     {
         ExecutionLog.Debug($"Missing data. No match cache item for id={Id}.");
         return null;
     }
     return ExceptionStrategy == ExceptionHandlingStrategy.THROW
         ? await matchCI.GetFixtureAsync(Cultures).ConfigureAwait(false)
         : await new Func<IEnumerable<CultureInfo>, Task<IFixture>>(matchCI.GetFixtureAsync).SafeInvokeAsync(Cultures, ExecutionLog, GetFetchErrorMessage("Fixture")).ConfigureAwait(false);
 }
Example #9
0
        /// <summary>
        /// Asynchronously gets the list of associated <see cref="IDraw"/>
        /// </summary>
        /// <returns>A <see cref="Task{T}"/> representing an async operation</returns>
        public async Task <IEnumerable <IDraw> > GetDrawsAsync()
        {
            var lotteryCI = (LotteryCI)SportEventCache.GetEventCacheItem(Id);

            if (lotteryCI == null)
            {
                ExecutionLog.Debug($"Missing data. No lottery cache item for id={Id}.");
                return(null);
            }
            var item = ExceptionStrategy == ExceptionHandlingStrategy.THROW
                ? await lotteryCI.GetScheduledDrawsAsync().ConfigureAwait(false)
                : await new Func <Task <IEnumerable <URN> > >(lotteryCI.GetScheduledDrawsAsync).SafeInvokeAsync(ExecutionLog, GetFetchErrorMessage("ScheduledDraws")).ConfigureAwait(false);

            return(item.Select(s => new Draw(s, SportId, SportEventCache, Cultures, ExceptionStrategy)));
        }
Example #10
0
        /// <summary>
        /// Asynchronously gets a <see cref="IRound"/> representing the tournament round to which the sport event associated with the current instance belongs to
        /// </summary>
        /// <returns>A <see cref="Task{IRound}"/> representing the retrieval operation</returns>
        public async Task <IRound> GetTournamentRoundAsync()
        {
            var matchCI = (IMatchCI)SportEventCache.GetEventCacheItem(Id);

            if (matchCI == null)
            {
                ExecutionLog.Debug($"Missing data. No match cache item for id={Id}.");
                return(null);
            }
            var item = ExceptionStrategy == ExceptionHandlingStrategy.THROW
                ? await matchCI.GetTournamentRoundAsync(Cultures).ConfigureAwait(false)
                : await new Func <IEnumerable <CultureInfo>, Task <RoundCI> >(matchCI.GetTournamentRoundAsync).SafeInvokeAsync(Cultures, ExecutionLog, GetFetchErrorMessage("Round")).ConfigureAwait(false);

            return(item == null ? null : new Round(item, Cultures));
        }
Example #11
0
        /// <summary>
        /// Asynchronously gets <see cref="T:System.Collections.Generic.IEnumerable`1" /> list of associated <see cref="T:Sportradar.OddsFeed.SDK.Entities.REST.IDrawResult" />
        /// </summary>
        /// <returns>A <see cref="T:System.Threading.Tasks.Task`1" /> representing an async operation</returns>
        /// <exception cref="System.NotImplementedException"></exception>
        public async Task <IEnumerable <IDrawResult> > GetResultsAsync()
        {
            var drawCI = (DrawCI)SportEventCache.GetEventCacheItem(Id);

            if (drawCI == null)
            {
                ExecutionLog.Debug($"Missing data. No draw cache item for id={Id}.");
                return(null);
            }
            var item = ExceptionStrategy == ExceptionHandlingStrategy.THROW
                ? await drawCI.GetResultsAsync(Cultures).ConfigureAwait(false)
                : await new Func <IEnumerable <CultureInfo>, Task <IEnumerable <DrawResultCI> > >(drawCI.GetResultsAsync).SafeInvokeAsync(Cultures, ExecutionLog, "DrawResults").ConfigureAwait(false);

            return(item?.Select(s => new DrawResult(s)));
        }
Example #12
0
        /// <summary>
        /// Asynchronously gets a liveOdds
        /// </summary>
        /// <returns>A liveOdds</returns>
        public async Task <string> GetLiveOddsAsync()
        {
            var competitionCI = (CompetitionCI)SportEventCache.GetEventCacheItem(Id);

            if (competitionCI == null)
            {
                ExecutionLog.Debug($"Missing data. No match cache item for id={Id}.");
                return(null);
            }
            var liveOdds = ExceptionStrategy == ExceptionHandlingStrategy.THROW
                ? await competitionCI.GetLiveOddsAsync().ConfigureAwait(false)
                : await new Func <Task <string> >(competitionCI.GetLiveOddsAsync).SafeInvokeAsync(ExecutionLog, GetFetchErrorMessage("LiveOdds")).ConfigureAwait(false);

            return(liveOdds);
        }
Example #13
0
        /// <summary>
        /// Asynchronously gets <see cref="DrawStatus" /> associated with the current instance
        /// </summary>
        /// <returns>A <see cref="T:System.Threading.Tasks.Task`1" /> representing an async operation</returns>
        /// <exception cref="System.NotImplementedException"></exception>
        public async Task <DrawStatus> GetStatusAsync()
        {
            var drawCI = (DrawCI)SportEventCache.GetEventCacheItem(Id);

            if (drawCI == null)
            {
                ExecutionLog.Debug($"Missing data. No draw cache item for id={Id}.");
                return(DrawStatus.Unknown);
            }
            var item = ExceptionStrategy == ExceptionHandlingStrategy.THROW
                ? await drawCI.GetStatusAsync().ConfigureAwait(false)
                : await new Func <Task <DrawStatus> >(drawCI.GetStatusAsync).SafeInvokeAsync(ExecutionLog, "DrawStatus").ConfigureAwait(false);

            return(item);
        }
 /// <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);
 }
Example #15
0
        /// <summary>
        /// Asynchronously gets a <see cref="ILongTermEvent"/> representing the tournament to which the sport event associated with the current instance belongs to
        /// </summary>
        /// <returns>A <see cref="Task{ILongTermEvent}"/> representing the retrieval operation</returns>
        public async Task<ILongTermEvent> GetTournamentAsync()
        {
            var matchCI = (IMatchCI)SportEventCache.GetEventCacheItem(Id);
            if (matchCI == null)
            {
                ExecutionLog.Debug($"Missing data. No match cache item for id={Id}.");
                return null;
            }
            var tournamentId = ExceptionStrategy == ExceptionHandlingStrategy.THROW
                ? await matchCI.GetTournamentIdAsync(Cultures).ConfigureAwait(false)
                : await new Func<IEnumerable<CultureInfo>, Task<URN>>(matchCI.GetTournamentIdAsync).SafeInvokeAsync(Cultures, ExecutionLog, GetFetchErrorMessage("ILongTermEvent")).ConfigureAwait(false);

            return tournamentId == null
                ? null
                : _sportEntityFactory.BuildSportEvent<ILongTermEvent>(tournamentId, SportId, Cultures, ExceptionStrategy);
        }
        /// <summary>
        /// Asynchronously gets a <see cref="ISportEventConditions"/> instance representing live conditions of the sport event associated with the current instance
        /// </summary>
        /// <returns>A <see cref="Task{IVenue}"/> representing the retrieval operation</returns>
        /// <remarks>A Fixture is a sport event that has been arranged for a particular time and place</remarks>
        public async Task<ISportEventConditions> GetConditionsAsync()
        {
            var competitionCI = (CompetitionCI)SportEventCache.GetEventCacheItem(Id);
            if (competitionCI == null)
            {
                ExecutionLog.Debug($"Missing data. No sportEvent cache item for id={Id}.");
                return null;
            }
            var item = ExceptionStrategy == ExceptionHandlingStrategy.THROW
                ? await competitionCI.GetConditionsAsync(Cultures).ConfigureAwait(false)
                : await new Func<IEnumerable<CultureInfo>, Task<SportEventConditionsCI>>(competitionCI.GetConditionsAsync).SafeInvokeAsync(Cultures, ExecutionLog, GetFetchErrorMessage("EventConditions")).ConfigureAwait(false);

            return item == null
                ? null
                : new SportEventConditions(item, Cultures);
        }
Example #17
0
        public async Task <IEnumerable <IStage> > GetStagesAsync()
        {
            var stageCI = (StageCI)SportEventCache.GetEventCacheItem(Id);

            if (stageCI == null)
            {
                ExecutionLog.Debug($"Missing data. No stage cache item for id={Id}.");
                return(null);
            }
            var cacheItems = ExceptionStrategy == ExceptionHandlingStrategy.CATCH
                ? await stageCI.GetStagesAsync(Cultures).ConfigureAwait(false)
                : await new Func <IEnumerable <CultureInfo>, Task <IEnumerable <StageCI> > >(stageCI.GetStagesAsync)
                             .SafeInvokeAsync(Cultures, ExecutionLog, GetFetchErrorMessage("ChildStages")).ConfigureAwait(false);

            return(cacheItems?.Select(c => new Stage(c.Id, GetSportAsync().Result.Id, _sportEntityFactory, SportEventCache, _sportDataCache, SportEventStatusCache, _matchStatusesCache, Cultures, ExceptionStrategy)));
        }
Example #18
0
        /// <summary>
        /// Asynchronously gets <see cref="IDrawInfo"/> associated with the current instance
        /// </summary>
        /// <returns>A <see cref="Task{T}"/> representing an async operation</returns>
        public async Task <IDrawInfo> GetDrawInfoAsync()
        {
            var lotteryCI = (LotteryCI)SportEventCache.GetEventCacheItem(Id);

            if (lotteryCI == null)
            {
                ExecutionLog.Debug($"Missing data. No lottery cache item for id={Id}.");
                return(null);
            }
            var item = ExceptionStrategy == ExceptionHandlingStrategy.THROW
                ? await lotteryCI.GetDrawInfoAsync().ConfigureAwait(false)
                : await new Func <Task <DrawInfoCI> >(lotteryCI.GetDrawInfoAsync).SafeInvokeAsync(ExecutionLog, GetFetchErrorMessage("DrawInfo")).ConfigureAwait(false);

            return(item == null
                ? null
                : new DrawInfo(item));
        }
Example #19
0
        /// <summary>
        /// Asynchronously gets a <see cref="IVenue"/> instance representing a venue where the sport event associated with the
        /// current instance will take place
        /// </summary>
        /// <returns>A <see cref="Task{IVenue}"/> representing the retrieval operation</returns>
        public async Task <IVenue> GetVenueAsync()
        {
            var competitionCI = (CompetitionCI)SportEventCache.GetEventCacheItem(Id);

            if (competitionCI == null)
            {
                ExecutionLog.Debug($"Missing data. No sportEvent cache item for id={Id}.");
                return(null);
            }
            var item = ExceptionStrategy == ExceptionHandlingStrategy.THROW
                ? await competitionCI.GetVenueAsync(Cultures).ConfigureAwait(false)
                : await new Func <IEnumerable <CultureInfo>, Task <VenueCI> >(competitionCI.GetVenueAsync).SafeInvokeAsync(Cultures, ExecutionLog, "Venue").ConfigureAwait(false);

            return(item == null
                ? null
                : new Venue(item, Cultures));
        }
Example #20
0
        /// <summary>
        /// Asynchronously gets the associated delayed info
        /// </summary>
        /// <returns>A <see cref="T:System.Threading.Tasks.Task`1" /> representing the retrieval operation</returns>
        /// <exception cref="NotImplementedException"></exception>
        public async Task <IDelayedInfo> GetDelayedInfoAsync()
        {
            var matchCI = (MatchCI)SportEventCache.GetEventCacheItem(Id);

            if (matchCI == null)
            {
                ExecutionLog.Debug($"Missing data. No match cache item for id={Id}.");
                return(null);
            }
            var delayedInfoCI = ExceptionStrategy == ExceptionHandlingStrategy.THROW
                ? await matchCI.GetDelayedInfoAsync(Cultures).ConfigureAwait(false)
                : await new Func <IEnumerable <CultureInfo>, Task <DelayedInfoCI> >(matchCI.GetDelayedInfoAsync).SafeInvokeAsync(Cultures, ExecutionLog, GetFetchErrorMessage("DelayedInfo")).ConfigureAwait(false);

            return(delayedInfoCI == null
                ? null
                : new DelayedInfo(delayedInfoCI));
        }
Example #21
0
        /// <summary>
        /// Asynchronously gets the associated event timeline for single culture
        /// </summary>
        /// <param name="culture">The languages to which the returned instance should be translated</param>
        /// <remarks>Recommended to be used when only <see cref="IEventTimeline"/> is needed for this <see cref="IMatch"/></remarks>
        /// <returns>A <see cref="Task{IEventTimeline}"/> representing the retrieval operation</returns>
        public async Task<IEventTimeline> GetEventTimelineAsync(CultureInfo culture)
        {
            var matchCI = (IMatchCI)SportEventCache.GetEventCacheItem(Id);
            if (matchCI == null)
            {
                ExecutionLog.Debug($"Missing data. No match cache item for id={Id}.");
                return null;
            }

            var oneCulture = new List<CultureInfo> {culture ?? Cultures.First()};
            var eventTimelineCI = ExceptionStrategy == ExceptionHandlingStrategy.THROW
                ? await matchCI.GetEventTimelineAsync(oneCulture).ConfigureAwait(false)
                : await new Func<IEnumerable<CultureInfo>, Task<EventTimelineCI>>(matchCI.GetEventTimelineAsync).SafeInvokeAsync(oneCulture, ExecutionLog, GetFetchErrorMessage("EventTimeline")).ConfigureAwait(false);

            return eventTimelineCI == null
                ? null
                : new EventTimeline(eventTimelineCI);
        }
Example #22
0
        public async Task <IStage> GetParentStageAsync()
        {
            var stageCI = (StageCI)SportEventCache.GetEventCacheItem(Id);

            if (stageCI == null)
            {
                ExecutionLog.Debug($"Missing data. No stage cache item for id={Id}.");
                return(null);
            }

            var parentStageId = await stageCI.GetParentStageAsync(Cultures).ConfigureAwait(false);

            if (parentStageId != null)
            {
                return(new Stage(parentStageId, GetSportAsync().Result.Id, _sportEntityFactory, SportEventCache, _sportDataCache, SportEventStatusCache, MatchStatusCache, Cultures, ExceptionStrategy));
            }

            return(null);
        }
Example #23
0
        public async Task <ISportSummary> GetSportAsync()
        {
            var stageCI = (StageCI)SportEventCache.GetEventCacheItem(Id);

            if (stageCI == null)
            {
                ExecutionLog.Debug($"Missing data. No stage cache item for id={Id}.");
                return(null);
            }
            var sportId = await stageCI.GetSportIdAsync().ConfigureAwait(false);

            if (sportId == null)
            {
                ExecutionLog.Debug($"Missing data. No sportId for stage cache item with id={Id}.");
                return(null);
            }
            var sportCI = await _sportDataCache.GetSportAsync(sportId, Cultures).ConfigureAwait(false);

            return(sportCI == null ? null : new SportSummary(sportCI.Id, sportCI.Names));
        }
Example #24
0
        /// <summary>
        ///     Adds the sport event status to the internal cache
        /// </summary>
        /// <param name="eventId">The eventId of the sport event status to be cached</param>
        /// <param name="sportEventStatus">The sport event status to be cached</param>
        /// <param name="source">The source of the SES</param>
        private void AddSportEventStatus(URN eventId, SportEventStatusCI sportEventStatus, string source)
        {
            if (_isDisposed)
            {
                return;
            }

            lock (_lock)
            {
                if (string.IsNullOrEmpty(source) ||
                    source.Equals("OddsChange", StringComparison.InvariantCultureIgnoreCase) ||
                    source.Equals("SportEventSummary", StringComparison.InvariantCultureIgnoreCase) ||
                    !_sportEventStatusCache.Contains(eventId.ToString()))
                {
                    if (!string.IsNullOrEmpty(source))
                    {
                        source = $" from {source}";
                    }
                    ExecutionLog.Debug(
                        $"Received SES for {eventId}{source} with EventStatus:{sportEventStatus.Status}");
                    var cacheItem = _sportEventStatusCache.AddOrGetExisting(eventId.ToString(),
                                                                            sportEventStatus,
                                                                            new CacheItemPolicy
                    {
                        AbsoluteExpiration = DateTimeOffset.Now.AddSeconds(_cacheItemExpireTime.TotalSeconds)
                    })
                                    as SportEventStatusCI;
                    if (cacheItem != null)
                    {
                        cacheItem.SetFeedStatus(sportEventStatus.FeedStatusDTO);
                        cacheItem.SetSapiStatus(sportEventStatus.SapiStatusDTO);
                    }
                }
                else
                {
                    ExecutionLog.Debug(
                        $"Received SES for {eventId} from {source} with EventStatus:{sportEventStatus.Status} (ignored)");
                }
            }
        }
Example #25
0
        public async Task <ICategorySummary> GetCategoryAsync()
        {
            var stageCI = (StageCI)SportEventCache.GetEventCacheItem(Id);

            if (stageCI == null)
            {
                ExecutionLog.Debug($"Missing data. No stage cache item for id={Id}.");
                return(null);
            }
            var categoryId = await stageCI.GetCategoryIdAsync().ConfigureAwait(false);

            if (categoryId == null)
            {
                ExecutionLog.Debug($"Missing data. No categoryId for stage cache item with id={Id}.");
                return(null);
            }
            var categoryCI = await _sportDataCache.GetCategoryAsync(categoryId, Cultures).ConfigureAwait(false);

            return(categoryCI == null
                ? null
                : new CategorySummary(categoryCI.Id, categoryCI.Names, categoryCI.CountryCode));
        }
Example #26
0
        /// <summary>
        /// Asynchronously gets a <see cref="PlayerProfileCI"/> representing the profile for the specified player
        /// </summary>
        /// <param name="playerId">A <see cref="URN"/> specifying the id of the player for which to get the profile</param>
        /// <param name="cultures">A <see cref="IEnumerable{CultureInfo}"/> specifying languages in which the information should be available</param>
        /// <returns>A <see cref="Task{PlayerProfileCI}"/> representing the asynchronous operation</returns>
        /// <exception cref="CacheItemNotFoundException">The requested item was not found in cache and could not be obtained from the API</exception>
        public async Task <PlayerProfileCI> GetPlayerProfileAsync(URN playerId, IEnumerable <CultureInfo> cultures)
        {
            Guard.Argument(playerId, nameof(playerId)).NotNull();
            Guard.Argument(cultures, nameof(cultures)).NotNull().NotEmpty();

            Metric.Context("CACHE").Meter("ProfileCache->GetPlayerProfileAsync", Unit.Calls);

            await _semaphorePlayer.WaitAsync().ConfigureAwait(false);

            PlayerProfileCI cachedItem;

            try
            {
                cachedItem = (PlayerProfileCI)_cache.Get(playerId.ToString());
                var wantedCultures   = cultures.ToList();
                var missingLanguages = LanguageHelper.GetMissingCultures(wantedCultures, cachedItem?.Names.Keys).ToList();
                if (!missingLanguages.Any())
                {
                    return(cachedItem);
                }

                // try to fetch for competitor, to avoid requests by each player
                if (cachedItem?.CompetitorId != null)
                {
                    var competitorCI = (CompetitorCI)_cache.Get(cachedItem.CompetitorId.ToString());
                    if (competitorCI != null &&
                        (competitorCI.LastTimeCompetitorProfileFetched < DateTime.Now.AddSeconds(-30) ||
                         LanguageHelper.GetMissingCultures(wantedCultures, competitorCI.CultureCompetitorProfileFetched).Any()))
                    {
                        ExecutionLog.Debug($"Fetching competitor profile for competitor {competitorCI.Id} instead of player {cachedItem.Id} for languages=[{string.Join(",", missingLanguages.Select(s => s.TwoLetterISOLanguageName))}].");

                        try
                        {
                            await _semaphoreCompetitor.WaitAsync().ConfigureAwait(false);

                            var cultureTasks = missingLanguages.ToDictionary(c => c, c => _dataRouterManager.GetCompetitorAsync(competitorCI.Id, c, null));
                            await Task.WhenAll(cultureTasks.Values).ConfigureAwait(false);
                        }
                        catch (Exception)
                        {
                            // ignored
                        }
                        finally
                        {
                            if (!_isDisposed)
                            {
                                _semaphoreCompetitor.Release();
                            }
                        }

                        cachedItem       = (PlayerProfileCI)_cache.Get(playerId.ToString());
                        missingLanguages = LanguageHelper.GetMissingCultures(wantedCultures, cachedItem?.Names.Keys).ToList();
                        if (!missingLanguages.Any())
                        {
                            return(cachedItem);
                        }
                    }
                }

                var cultureTaskDictionary = missingLanguages.ToDictionary(c => c, c => _dataRouterManager.GetPlayerProfileAsync(playerId, c, null));
                await Task.WhenAll(cultureTaskDictionary.Values).ConfigureAwait(false);

                cachedItem = (PlayerProfileCI)_cache.Get(playerId.ToString());
            }
            catch (Exception ex)
            {
                if (ex is DeserializationException || ex is MappingException)
                {
                    throw new CacheItemNotFoundException($"An error occurred while fetching player profile for player {playerId} in cache", playerId.ToString(), ex);
                }
                throw;
            }
            finally
            {
                if (!_isDisposed)
                {
                    _semaphorePlayer.Release();
                }
            }
            return(cachedItem);
        }
Example #27
0
        private void AddSportEvent(URN id, SportEventSummaryDTO item, CultureInfo culture, ISportEventCI requester, DtoType dtoType)
        {
            TournamentInfoDTO tournamentInfoDTO = null;

            lock (_addLock)
            {
                try
                {
                    var cacheItem = _sportEventCacheItemFactory.Get(Cache.Get(id.ToString()));

                    if (requester != null && !Equals(requester, cacheItem) && id.Equals(requester.Id))
                    {
                        try
                        {
                            var requesterMerged = false;
                            var fixture         = item as FixtureDTO;
                            if (fixture != null)
                            {
                                if (requester.Id.TypeGroup == ResourceTypeGroup.MATCH)
                                {
                                    ((MatchCI)requester).MergeFixture(fixture, culture, true);
                                }
                                else if (requester.Id.TypeGroup == ResourceTypeGroup.STAGE)
                                {
                                    ((StageCI)requester).MergeFixture(fixture, culture, true);
                                }
                                else
                                {
                                    ((TournamentInfoCI)requester).MergeFixture(fixture, culture, true);
                                }
                                requesterMerged = true;
                            }
                            if (!requesterMerged)
                            {
                                var match = item as MatchDTO;
                                if (match != null)
                                {
                                    ((MatchCI)requester).Merge(match, culture, true);
                                    requesterMerged = true;
                                }
                            }
                            if (!requesterMerged)
                            {
                                var stage = item as StageDTO;
                                if (stage != null)
                                {
                                    ((StageCI)requester).Merge(stage, culture, true);
                                    requesterMerged = true;
                                }
                            }
                            if (!requesterMerged)
                            {
                                var tour = item as TournamentInfoDTO;
                                if (tour != null)
                                {
                                    var stageCI = requester as StageCI;
                                    if (stageCI != null)
                                    {
                                        stageCI.Merge(tour, culture, true);
                                        requesterMerged = true;
                                    }
                                    else
                                    {
                                        var tourCI = requester as TournamentInfoCI;
                                        if (tourCI != null)
                                        {
                                            tourCI.Merge(tour, culture, true);
                                            requesterMerged = true;
                                        }
                                    }
                                }
                            }
                            if (!requesterMerged)
                            {
                                var draw = item as DrawDTO;
                                if (draw != null)
                                {
                                    ((DrawCI)requester).Merge(draw, culture, true);
                                    requesterMerged = true;
                                }
                            }
                            if (!requesterMerged)
                            {
                                var lottery = item as LotteryDTO;
                                if (lottery != null)
                                {
                                    ((LotteryCI)requester).Merge(lottery, culture, true);
                                    requesterMerged = true;
                                }
                            }
                            if (!requesterMerged)
                            {
                                requester.Merge(item, culture, true);
                            }
                        }
                        catch (Exception)
                        {
                            ExecutionLog.Debug($"Merging failed for {id} and item type: {item.GetType().Name} and dto type: {dtoType} for requester: {requester.Id}.");
                        }
                    }

                    if (cacheItem != null)
                    {
                        //ExecutionLog.Debug($"Saving OLD data for {id} and item type: {item.GetType().Name} and dto type: {dtoType}.");
                        var merged = false;
                        //var cacheItem = _sportEventCacheItemFactory.Get(Cache.Get(id.ToString()));
                        var fixture = item as FixtureDTO;
                        if (fixture != null)
                        {
                            if (cacheItem.Id.TypeGroup == ResourceTypeGroup.MATCH)
                            {
                                ((MatchCI)cacheItem).MergeFixture(fixture, culture, true);
                            }
                            else if (cacheItem.Id.TypeGroup == ResourceTypeGroup.STAGE)
                            {
                                ((StageCI)cacheItem).MergeFixture(fixture, culture, true);
                            }
                            else
                            {
                                ((TournamentInfoCI)cacheItem).MergeFixture(fixture, culture, true);
                            }
                            if (fixture.Tournament != null)
                            {
                                tournamentInfoDTO = new TournamentInfoDTO(fixture.Tournament);
                            }
                            merged = true;
                        }
                        if (!merged)
                        {
                            var stage = item as StageDTO;
                            if (stage != null)
                            {
                                ((StageCI)cacheItem).Merge(stage, culture, true);
                                merged = true;
                                if (stage.Tournament != null)
                                {
                                    tournamentInfoDTO = new TournamentInfoDTO(stage.Tournament);
                                }
                            }
                        }
                        if (!merged)
                        {
                            var tour = item as TournamentInfoDTO;
                            if (tour != null)
                            {
                                var stageCI = cacheItem as StageCI;
                                if (stageCI != null)
                                {
                                    stageCI.Merge(tour, culture, true);
                                    merged = true;
                                }
                                else
                                {
                                    var tourCI = cacheItem as TournamentInfoCI;
                                    if (tourCI != null)
                                    {
                                        tourCI.Merge(tour, culture, true);
                                        merged = true;
                                    }
                                }
                            }
                        }
                        if (!merged)
                        {
                            var match = item as MatchDTO;
                            if (match != null)
                            {
                                ((MatchCI)cacheItem).Merge(match, culture, true);
                                merged = true;
                                if (match.Tournament != null)
                                {
                                    tournamentInfoDTO = new TournamentInfoDTO(match.Tournament);
                                }
                            }
                        }
                        if (!merged)
                        {
                            var draw = item as DrawDTO;
                            if (draw != null)
                            {
                                ((DrawCI)cacheItem).Merge(draw, culture, true);
                                merged = true;
                            }
                        }
                        if (!merged)
                        {
                            var lottery = item as LotteryDTO;
                            if (lottery != null)
                            {
                                ((LotteryCI)cacheItem).Merge(lottery, culture, true);
                                merged = true;
                            }
                        }
                        if (!merged)
                        {
                            cacheItem.Merge(item, culture, true);
                        }
                    }
                    else
                    {
                        //ExecutionLog.Debug($"Saving NEW data for {id} and item type: {item.GetType().Name} and dto type: {dtoType}.");
                        var ci = _sportEventCacheItemFactory.Build(item, culture);
                        if (dtoType == DtoType.SportEventSummary || dtoType == DtoType.LotteryDraw || dtoType == DtoType.MatchSummary)
                        {
                            ci.LoadedSummaries.Add(culture);
                        }
                        else if (dtoType == DtoType.Fixture)
                        {
                            ci.LoadedFixtures.Add(culture);
                        }
                        AddNewCacheItem(ci);
                        if (!ci.Id.Equals(id))
                        {
                            var tInfo = item as TournamentInfoDTO;
                            if (tInfo != null)
                            {
                                var newTournamentDto = new TournamentInfoDTO(tInfo, tInfo.Season != null, tInfo.CurrentSeason != null);
                                var ci2 = _sportEventCacheItemFactory.Build(newTournamentDto, culture);
                                AddNewCacheItem(ci2);
                            }
                            else
                            {
                                var ci2 = _sportEventCacheItemFactory.Build(item, culture);
                                ci2.Id = id;
                                AddNewCacheItem(ci2);
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    ExecutionLog.Error($"Error adding sport event for id={id}, dto type={item?.GetType().Name} and lang={culture.TwoLetterISOLanguageName}.", ex);
                }
            }

            // if there are events for non-standard tournaments (tournaments not on All tournaments for all sports)
            // TODO: should we save/merge all, or just adding non-existing???
            if (tournamentInfoDTO != null && (SpecialTournaments.Contains(tournamentInfoDTO.Id) || !Cache.Contains(tournamentInfoDTO.Id.ToString())))
            {
                if (SpecialTournaments.Contains(tournamentInfoDTO.Id))
                {
                    //ExecutionLog.Debug($"Updating tournament id={tournamentInfoDTO.Id}, introduced by event id={id} and lang=[{culture.TwoLetterISOLanguageName}].");
                }
                else
                {
                    //ExecutionLog.Debug($"Saving tournament id={tournamentInfoDTO.Id}, introduced by event id={id} and lang=[{culture.TwoLetterISOLanguageName}].");
                    SpecialTournaments.Add(tournamentInfoDTO.Id);
                }
                AddSportEvent(tournamentInfoDTO.Id, tournamentInfoDTO, culture, null, dtoType);
            }
        }