Example #1
0
        public async Task <UpsertPlaysResult> UpsertPlaysAsync(BoardGame boardGame, List <Play> plays, CancellationToken cancellationToken)
        {
            UpsertPlaysResult upsertResult = new UpsertPlaysResult();

            if (plays?.Any() != true)
            {
                _logger.Warning("Attempted to log an empty play list");
                return(upsertResult);
            }

            IMongoDatabase          database   = _client.GetDatabase(Database);
            IMongoCollection <Play> collection = database.GetCollection <Play>(PlayCollection);

            _logger.Verbose("Upserting {Count} plays for ObjectId {ObjectID}", plays.Count, plays[0].ObjectId);

            foreach (Play play in plays)
            {
                try
                {
                    ReplaceOneResult result =
                        await collection.ReplaceOneAsync(
                            x => x.Id == play.Id, play,
                            new ReplaceOptions { IsUpsert = true },
                            cancellationToken);

                    if (result.ModifiedCount == 0 && result.MatchedCount == 0 && result.UpsertedId != null)
                    {
                        upsertResult.InsertedCount++;
                    }

                    upsertResult.MatchedCount  += result.MatchedCount;
                    upsertResult.ModifiedCount += result.ModifiedCount;
                    upsertResult.WasSuccessful  = true;
                }
                catch (OperationCanceledException)
                {
                    _logger.Warning("Aborting upsert, the operation has been canceled");
                    return(upsertResult);
                }
                catch (Exception ex)
                {
                    _logger.Error(ex,
                                  "Failed to upsert play {PlayId} for {GameName}: {ErrorMessage}",
                                  play.Id,
                                  boardGame.Name,
                                  ex.Message);
                }
            }

            return(upsertResult);
        }
        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);
        }