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); }