Exemple #1
0
        public async Task UpsertBoardGameStatusAsync(BoardGameStatus status, CancellationToken cancellationToken)
        {
            if (status == null)
            {
                _logger.Warning("Attempted to upsert a null status");
                return;
            }

            IMongoDatabase database = _client.GetDatabase(Database);
            IMongoCollection <BoardGameStatus> collection = database.GetCollection <BoardGameStatus>(BoardGameStatusCollection);

            _logger.Verbose("Upserting status for {ObjectId}", status.ObjectId);

            try
            {
                await collection.ReplaceOneAsync(
                    x => x.ObjectId == status.ObjectId,
                    status,
                    new ReplaceOptions { IsUpsert = true },
                    cancellationToken);
            }
            catch (OperationCanceledException)
            {
                _logger.Warning("Aborting upsert, the operation has been cancelled");
            }
            catch (Exception ex)
            {
                _logger.Error(ex,
                              "Failed to upsert board game status for {GameName}: {ErrorMessage}",
                              status.BoardGameName,
                              ex.Message);
            }
        }
        private async Task RunAsync()
        {
            _logger.Verbose("Running {ClassName}", nameof(PlayLogger));

            bool error = false;

            try
            {
                _logger.Information($"Beginning update loop...{Environment.NewLine}");

                while (!(_cancellationToken.IsCancellationRequested || error))
                {
                    List <BoardGame> boardGames = await _mongoSvc.GetBoardListAsync(_cancellationToken);

                    BoardGame lastGame = boardGames.Last();

                    _logger.Information("Will log plays for {GameCount} games:", boardGames.Count);
                    boardGames.ForEach(
                        bg => _logger.Information(
                            $"\t- {{GameName}} - {{GameId}}{(bg == lastGame? Environment.NewLine : String.Empty)}",
                            bg.Name,
                            bg.ObjectId));

                    foreach (BoardGame bg in boardGames)
                    {
                        try
                        {
                            if (!_cancellationToken.IsCancellationRequested)
                            {
                                _logger.Information("Starting play logging for {GameName}", bg.Name);
                                BoardGameStatus status = await _mongoSvc.GetBoardGameStatusAsync(bg.ObjectId, _cancellationToken);

                                if (status?.ImportSuccessful == true)
                                {
                                    await GetMostRecentPlaysAsync(bg, status);
                                }
                                else
                                {
                                    await GetAllPlaysAsync(bg);
                                }

                                _logger.Information($"Completed updating plays for {{GameName}}{Environment.NewLine}", bg.Name);
                            }
                            else
                            {
                                _logger.Information("Skipping {GameName}, service is shutting down", bg.Name);
                            }
                        }
                        catch (Exception ex)
                        {
                            _logger.Error(ex, "Failed to get plays for {GameName}", bg.Name);
                            error = true;
                        }
                    }

                    if (!_cancellationToken.IsCancellationRequested)
                    {
                        _logger.Information("Finished processing list, will update in {Minutes} minutes", _config.UpdateDelayInMinutes);
                        await Task
                        .Delay(TimeSpan.FromMinutes(_config.UpdateDelayInMinutes), _cancellationToken)
                        .ContinueWith(t => { }, CancellationToken.None);
                    }
                }
            }
            catch (Exception ex)
            {
                _logger.Error(ex, "Something went terribly wrong: {Message}", ex.Message);
            }
        }
        private async Task GetMostRecentPlaysAsync(BoardGame boardGame, BoardGameStatus status)
        {
            if (!(_config.OnlyUpdateOncePerDay && status.LastUpdated.Date == DateTime.Now.Date))
            {
                DateTime maxDate = DateTime.Now;
                DateTime minDate = maxDate.AddDays(-_config.IncrementalSpanInDays);
                int      page    = 1;

                _logger.Information(
                    "Getting plays between {MinDate} and {MaxDate} ({DayCount} days) for {BoardGameName}",
                    minDate.Date.ToShortDateString(),
                    maxDate.Date.ToShortDateString(),
                    maxDate.Subtract(minDate).TotalDays,
                    boardGame.Name);

                GetPlaysResult result;

                do
                {
                    result = await _bggSvc.GetPlaysAsync(boardGame.ObjectId, minDate, maxDate, page);

                    if (result.TooManyRequests)
                    {
                        _logger.Warning("Too many requests, will wait to resume...");
                        await Task.Delay(TimeSpan.FromSeconds(60), _cancellationToken)
                        .ContinueWith(t => { }, CancellationToken.None);

                        continue;
                    }

                    if (!result.WasSuccessful)
                    {
                        _logger.Error("Failed to get plays, not sure what to do now...");
                        await Task.Delay(TimeSpan.FromSeconds(3), _cancellationToken)
                        .ContinueWith(t => { }, CancellationToken.None);

                        continue;
                    }

                    _logger.Information(
                        "Successfully downloaded page {CurrentPage} of {TotalPages}",
                        result.Page,
                        Math.Ceiling(result.TotalCount / 100d));

                    UpsertPlaysResult upsertResult =
                        await _mongoSvc.UpsertPlaysAsync(boardGame, result.Plays, _cancellationToken);

                    if (!upsertResult.WasSuccessful)
                    {
                        _logger.Error("Failed to completed the upsert successfully");
                    }

                    _logger.Information(
                        "Upsert results: Matched {MatchedCount} - Modified {ModifiedCount} - Inserted {InsertedCount}",
                        upsertResult.MatchedCount,
                        upsertResult.ModifiedCount,
                        upsertResult.InsertedCount);

                    page++;
                } while ((!result.WasSuccessful || result.Plays.Count == MaxPlaysPerPage) && !_cancellationToken.IsCancellationRequested);
            }
            else
            {
                _logger.Information("Already logged plays for {BoardGameName} today", boardGame.Name);
            }

            status.LastUpdated = DateTime.Now;
            await _mongoSvc.UpsertBoardGameStatusAsync(status, _cancellationToken);
        }