/// <remarks>
        /// https://devblogs.microsoft.com/aspnet/queuebackgroundworkitem-to-reliably-schedule-and-run-background-processes-in-asp-net/
        /// </remarks>
        private async Task <CancellationToken> UpdateStatistics(Guid taskId, Guid memberKey, string memberName, CancellationToken cancellationToken)
        {
            try
            {
                Logger.Info(GetType(), "Updating match statistics for all matches in {Type:l}.{Method:l}.", GetType(), nameof(UpdateStatistics));

                var matchListings = (await _matchListingDataSource.ReadMatchListings(new MatchFilter
                {
                    IncludeMatches = true,
                    IncludeTournamentMatches = true,
                    IncludeTournaments = false,
                    UntilDate = DateTime.UtcNow
                }, MatchSortOrder.MatchDateEarliestFirst).ConfigureAwait(false));

                _taskTracker.SetTarget(taskId, matchListings.Sum(x => x.MatchInnings.Count) + matchListings.Count);

                using (var connection = _databaseConnectionFactory.CreateDatabaseConnection())
                {
                    connection.Open();

                    foreach (var matchListing in matchListings)
                    {
                        if (cancellationToken.IsCancellationRequested)
                        {
                            Logger.Warn(GetType(), "Background task cancellation requested in {Type:l}.{Method:l}.", GetType(), nameof(UpdateStatistics));
                        }

                        try
                        {
                            var match = await _matchDataSource.ReadMatchByRoute(matchListing.MatchRoute).ConfigureAwait(false);

                            if (match != null)
                            {
                                using (var transaction = connection.BeginTransaction())
                                {
                                    await _statisticsRepository.DeletePlayerStatistics(match.MatchId.Value, transaction).ConfigureAwait(false);

                                    foreach (var innings in match.MatchInnings)
                                    {
                                        await _statisticsRepository.DeleteBowlingFigures(innings.MatchInningsId.Value, transaction).ConfigureAwait(false);

                                        innings.BowlingFigures = _bowlingFiguresCalculator.CalculateBowlingFigures(innings);
                                        await _statisticsRepository.UpdateBowlingFigures(innings, memberKey, memberName, transaction).ConfigureAwait(false);

                                        _taskTracker.IncrementCompletedBy(taskId, 1);
                                    }

                                    var hasPlayerData = _playerIdentityFinder.PlayerIdentitiesInMatch(match).Any();
                                    if (hasPlayerData)
                                    {
                                        var statisticsData = _playerInMatchStatisticsBuilder.BuildStatisticsForMatch(match);
                                        await _statisticsRepository.UpdatePlayerStatistics(statisticsData, transaction).ConfigureAwait(false);
                                    }
                                    _taskTracker.IncrementCompletedBy(taskId, 1);
                                    transaction.Commit();
                                }
                            }
                        }
                        catch (Exception ex)
                        {
                            Logger.Error(GetType(), "Error '{Error}' updating match statistics for '{MatchRoute}' in {Type:l}.{Method:l}.", ex.Message, matchListing.MatchRoute, GetType(), nameof(UpdateStatistics));
                            _taskTracker.IncrementErrorsBy(taskId, 1);
                        }
                    }

                    using (var transaction = connection.BeginTransaction())
                    {
                        await _statisticsRepository.UpdatePlayerProbability(null, transaction).ConfigureAwait(false);

                        transaction.Commit();
                    }

                    Logger.Info(GetType(), "Completed updating match statistics for all matches in {Type:l}.{Method:l}.", GetType(), nameof(UpdateStatistics));
                }
            }
            catch (TaskCanceledException tce)
            {
                Logger.Error(GetType(), "Caught TaskCanceledException '{Message}' in {Type:l}.{Method:l}.", tce.Message, GetType(), nameof(UpdateStatistics));
            }

            return(cancellationToken);
        }