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