diff --git a/src/clients/common/Codebreaker.GameAPIs.Client.Tests/TestGamesClient.cs b/src/clients/common/Codebreaker.GameAPIs.Client.Tests/TestGamesClient.cs index 47ca7ead..84ad0fe8 100644 --- a/src/clients/common/Codebreaker.GameAPIs.Client.Tests/TestGamesClient.cs +++ b/src/clients/common/Codebreaker.GameAPIs.Client.Tests/TestGamesClient.cs @@ -1,13 +1,10 @@ +using Microsoft.Extensions.Logging.Abstractions; + namespace Codebreaker.GameAPIs.Client.Tests; -public class TestGamesClient +public class TestGamesClient(ITestOutputHelper outputHelper) { - private readonly ITestOutputHelper _outputHelper; - - public TestGamesClient(ITestOutputHelper outputHelper) - { - _outputHelper = outputHelper; - } + private readonly ITestOutputHelper _outputHelper = outputHelper; [Fact] public async Task TestStartGame6x4Async() @@ -51,8 +48,8 @@ public async Task TestStartGame6x4Async() { BaseAddress = new System.Uri(configMock.Object["GameAPIs"] ?? throw new InvalidOperationException()) }; - - var gamesClient = new GamesClient(httpClient); + + var gamesClient = new GamesClient(httpClient, NullLogger.Instance); // Act var response = await gamesClient.StartGameAsync(Models.GameType.Game6x4, "test"); diff --git a/src/clients/common/Codebreaker.GameAPIs.Client/Codebreaker.GameAPIs.Client.csproj b/src/clients/common/Codebreaker.GameAPIs.Client/Codebreaker.GameAPIs.Client.csproj index 284691f8..a4d6e2f2 100644 --- a/src/clients/common/Codebreaker.GameAPIs.Client/Codebreaker.GameAPIs.Client.csproj +++ b/src/clients/common/Codebreaker.GameAPIs.Client/Codebreaker.GameAPIs.Client.csproj @@ -22,4 +22,12 @@ + + + + + + + + diff --git a/src/clients/common/Codebreaker.GameAPIs.Client/GamesClient.cs b/src/clients/common/Codebreaker.GameAPIs.Client/GamesClient.cs index f0ccd55a..bfb72670 100644 --- a/src/clients/common/Codebreaker.GameAPIs.Client/GamesClient.cs +++ b/src/clients/common/Codebreaker.GameAPIs.Client/GamesClient.cs @@ -4,24 +4,22 @@ using Codebreaker.GameAPIs.Client.Models; +using Microsoft.Extensions.Logging; + namespace Codebreaker.GameAPIs.Client; /// /// Client to interact with the Codebreaker Game API. /// -public class GamesClient : IGamesClient +public class GamesClient(HttpClient httpClient, ILogger logger) : IGamesClient { - private readonly HttpClient _httpClient; + private readonly HttpClient _httpClient = httpClient; + private readonly ILogger _logger = logger; private readonly static JsonSerializerOptions s_jsonOptions = new() { PropertyNameCaseInsensitive = true }; - public GamesClient(HttpClient httpClient) - { - _httpClient = httpClient; - } - /// /// Starts a new game /// @@ -34,11 +32,19 @@ public GamesClient(HttpClient httpClient) public async Task<(Guid GameId, int NumberCodes, int MaxMoves, IDictionary FieldValues)> StartGameAsync(GameType gameType, string playerName, CancellationToken cancellationToken = default) { - CreateGameRequest createGameRequest = new(gameType, playerName); - var response = await _httpClient.PostAsJsonAsync("/games", createGameRequest, s_jsonOptions, cancellationToken); - response.EnsureSuccessStatusCode(); - var gameResponse = await response.Content.ReadFromJsonAsync(s_jsonOptions, cancellationToken) ?? throw new InvalidOperationException(); - return (gameResponse.GameId, gameResponse.NumberCodes, gameResponse.MaxMoves, gameResponse.FieldValues); + try + { + CreateGameRequest createGameRequest = new(gameType, playerName); + var response = await _httpClient.PostAsJsonAsync("/games", createGameRequest, s_jsonOptions, cancellationToken); + response.EnsureSuccessStatusCode(); + var gameResponse = await response.Content.ReadFromJsonAsync(s_jsonOptions, cancellationToken) ?? throw new InvalidOperationException(); + return (gameResponse.GameId, gameResponse.NumberCodes, gameResponse.MaxMoves, gameResponse.FieldValues); + } + catch (HttpRequestException ex) + { + _logger.LogError(ex, "StartGameAsync error {error}", ex.Message); + throw; + } } /// @@ -55,16 +61,24 @@ public GamesClient(HttpClient httpClient) /// public async Task<(string[] Results, bool Ended, bool IsVictory)> SetMoveAsync(Guid gameId, string playerName, GameType gameType, int moveNumber, string[] guessPegs, CancellationToken cancellationToken = default) { - UpdateGameRequest updateGameRequest = new(gameId, gameType, playerName, moveNumber) + try { - GuessPegs = guessPegs - }; - var response = await _httpClient.PatchAsJsonAsync($"/games/{gameId}", updateGameRequest, s_jsonOptions, cancellationToken); - response.EnsureSuccessStatusCode(); - var moveResponse = await response.Content.ReadFromJsonAsync(s_jsonOptions, cancellationToken) - ?? throw new InvalidOperationException(); - (_, _, _, bool ended, bool isVictory, string[] results) = moveResponse; - return (results, ended, isVictory); + UpdateGameRequest updateGameRequest = new(gameId, gameType, playerName, moveNumber) + { + GuessPegs = guessPegs + }; + var response = await _httpClient.PatchAsJsonAsync($"/games/{gameId}", updateGameRequest, s_jsonOptions, cancellationToken); + response.EnsureSuccessStatusCode(); + var moveResponse = await response.Content.ReadFromJsonAsync(s_jsonOptions, cancellationToken) + ?? throw new InvalidOperationException(); + (_, _, _, bool ended, bool isVictory, string[] results) = moveResponse; + return (results, ended, isVictory); + } + catch (HttpRequestException ex) + { + _logger.LogError(ex, "SetMoveAsync error {error}", ex.Message); + throw; + } } /// @@ -76,15 +90,21 @@ public GamesClient(HttpClient httpClient) /// public async Task GetGameAsync(Guid gameId, CancellationToken cancellationToken = default) { - GameInfo? game = default; + GameInfo? game; try { game = await _httpClient.GetFromJsonAsync($"/games/{gameId}", s_jsonOptions, cancellationToken); } catch (HttpRequestException ex) when (ex.StatusCode == HttpStatusCode.NotFound) { + _logger.LogInformation(ex, "GetGameAsync game not found - {error}", ex.Message); return default; } + catch (HttpRequestException ex) + { + _logger.LogError(ex, "GetGameAsync error {error}", ex.Message); + throw; + } return game; } @@ -97,7 +117,15 @@ public GamesClient(HttpClient httpClient) /// public async Task> GetGamesAsync(GamesQuery query, CancellationToken cancellationToken = default) { - IEnumerable games = (await _httpClient.GetFromJsonAsync>($"/games/{query.AsUrlQuery()}", s_jsonOptions, cancellationToken)) ?? Enumerable.Empty(); - return games; + try + { + IEnumerable games = (await _httpClient.GetFromJsonAsync>($"/games/{query.AsUrlQuery()}", s_jsonOptions, cancellationToken)) ?? Enumerable.Empty(); + return games; + } + catch (HttpRequestException ex) + { + _logger.LogError(ex, "GetGamesAsync error {error}", ex.Message); + throw; + } } }