Skip to content

Commit

Permalink
Merge pull request #94 from CodebreakerApp/93-httpclientliblogging
Browse files Browse the repository at this point in the history
client lib: add error logging #93
  • Loading branch information
christiannagel authored Oct 19, 2023
2 parents 3477306 + bff9a3b commit b5cb901
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 33 deletions.
Original file line number Diff line number Diff line change
@@ -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()
Expand Down Expand Up @@ -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<GamesClient>.Instance);

// Act
var response = await gamesClient.StartGameAsync(Models.GameType.Game6x4, "test");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,12 @@
<None Include="Images/codebreaker.jpeg" Pack="true" PackagePath="\" />
</ItemGroup>

<ItemGroup Condition="'$(TargetFramework)'=='net7.0'">
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="7.0.1" />
</ItemGroup>

<ItemGroup Condition="'$(TargetFramework)'=='net8.0'">
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="8.0.0-rc.2.23479.6" />
</ItemGroup>

</Project>
76 changes: 52 additions & 24 deletions src/clients/common/Codebreaker.GameAPIs.Client/GamesClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,22 @@

using Codebreaker.GameAPIs.Client.Models;

using Microsoft.Extensions.Logging;

namespace Codebreaker.GameAPIs.Client;

/// <summary>
/// Client to interact with the Codebreaker Game API.
/// </summary>
public class GamesClient : IGamesClient
public class GamesClient(HttpClient httpClient, ILogger<GamesClient> 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;
}

/// <summary>
/// Starts a new game
/// </summary>
Expand All @@ -34,11 +32,19 @@ public GamesClient(HttpClient httpClient)
public async Task<(Guid GameId, int NumberCodes, int MaxMoves, IDictionary<string, string[]> 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<CreateGameResponse>(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<CreateGameResponse>(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;
}
}

/// <summary>
Expand All @@ -55,16 +61,24 @@ public GamesClient(HttpClient httpClient)
/// <exception cref="InvalidOperationException"></exception>
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<UpdateGameResponse>(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<UpdateGameResponse>(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;
}
}

/// <summary>
Expand All @@ -76,15 +90,21 @@ public GamesClient(HttpClient httpClient)
/// <exception cref="HttpRequestException"></exception>
public async Task<GameInfo?> GetGameAsync(Guid gameId, CancellationToken cancellationToken = default)
{
GameInfo? game = default;
GameInfo? game;
try
{
game = await _httpClient.GetFromJsonAsync<GameInfo>($"/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;
}

Expand All @@ -97,7 +117,15 @@ public GamesClient(HttpClient httpClient)
/// <exception cref="HttpRequestException"></exception>
public async Task<IEnumerable<GameInfo>> GetGamesAsync(GamesQuery query, CancellationToken cancellationToken = default)
{
IEnumerable<GameInfo> games = (await _httpClient.GetFromJsonAsync<IEnumerable<GameInfo>>($"/games/{query.AsUrlQuery()}", s_jsonOptions, cancellationToken)) ?? Enumerable.Empty<GameInfo>();
return games;
try
{
IEnumerable<GameInfo> games = (await _httpClient.GetFromJsonAsync<IEnumerable<GameInfo>>($"/games/{query.AsUrlQuery()}", s_jsonOptions, cancellationToken)) ?? Enumerable.Empty<GameInfo>();
return games;
}
catch (HttpRequestException ex)
{
_logger.LogError(ex, "GetGamesAsync error {error}", ex.Message);
throw;
}
}
}

0 comments on commit b5cb901

Please sign in to comment.