diff --git a/Dockerfile b/Dockerfile index b3a9714..b2e1a55 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,6 @@ -# Adjust DOTNET_OS_VERSION as desired -ARG DOTNET_SDK_VERSION=9.0-preview +ARG DOTNET_VERSION=9.0 -FROM mcr.microsoft.com/dotnet/sdk:${DOTNET_SDK_VERSION}-alpine AS build +FROM mcr.microsoft.com/dotnet/sdk:${DOTNET_VERSION}-alpine AS build RUN dotnet workload install wasm-tools WORKDIR /src @@ -38,9 +37,9 @@ RUN set -ex; \ RUN dotnet publish --no-restore -c Release -o /app PointingParty # final stage/image -FROM mcr.microsoft.com/dotnet/aspnet:${DOTNET_SDK_VERSION}-alpine -ENV ASPNETCORE_URLS http://+:8080 -ENV ASPNETCORE_ENVIRONMENT Production +FROM mcr.microsoft.com/dotnet/aspnet:${DOTNET_VERSION}-alpine +ENV ASPNETCORE_URLS=http://+:8080 +ENV ASPNETCORE_ENVIRONMENT=Production EXPOSE 8080 WORKDIR /app COPY --from=build /app . diff --git a/PointingParty.Client.Tests/PointingParty.Client.Tests.csproj b/PointingParty.Client.Tests/PointingParty.Client.Tests.csproj index 00cc3cf..db01725 100644 --- a/PointingParty.Client.Tests/PointingParty.Client.Tests.csproj +++ b/PointingParty.Client.Tests/PointingParty.Client.Tests.csproj @@ -10,19 +10,19 @@ - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive - - + + runtime; build; native; contentfiles; analyzers; buildtransitive all - + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/PointingParty.Client/GameContext.cs b/PointingParty.Client/GameContext.cs index c0f74b3..af307b4 100644 --- a/PointingParty.Client/GameContext.cs +++ b/PointingParty.Client/GameContext.cs @@ -36,7 +36,7 @@ public void PublishEvents() logger.LogDebug("Publishing {count} events", Game.EventsToPublish.Count); foreach (var gameEvent in Game!.EventsToPublish) - _hub!.BroadcastGameEvent(gameEvent.GetType().ToString(), gameEvent); + _hub!.BroadcastGameEvent(gameEvent); Game.EventsToPublish.Clear(); } diff --git a/PointingParty.Client/PointingParty.Client.csproj b/PointingParty.Client/PointingParty.Client.csproj index b12e7f4..033de6f 100644 --- a/PointingParty.Client/PointingParty.Client.csproj +++ b/PointingParty.Client/PointingParty.Client.csproj @@ -13,9 +13,9 @@ - - - + + + diff --git a/PointingParty.Domain/IGameEventHub.cs b/PointingParty.Domain/IGameEventHub.cs index 90f715f..28a5e08 100644 --- a/PointingParty.Domain/IGameEventHub.cs +++ b/PointingParty.Domain/IGameEventHub.cs @@ -2,6 +2,5 @@ namespace PointingParty.Domain; public interface IGameEventHub { - // SignalR client doesn't support polymorphic serialization yet, so we send a type + object - public Task BroadcastGameEvent(string type, object gameEvent); -} \ No newline at end of file + public Task BroadcastGameEvent(object gameEvent); +} diff --git a/PointingParty/GameEventHub.cs b/PointingParty/GameEventHub.cs index e63d35f..332d646 100644 --- a/PointingParty/GameEventHub.cs +++ b/PointingParty/GameEventHub.cs @@ -17,46 +17,21 @@ public GameEventHub(ILogger logger) _logger = logger; } - public Task BroadcastGameEvent(string type, object gameEvent) + public async Task BroadcastGameEvent(object gameEvent) { - var jsonEvent = (JsonElement)gameEvent; - var targetType = typeof(IGameEvent).Assembly.GetType(type); - - if (targetType is null) + if (gameEvent is not JsonElement jsonEvent) { - _logger.LogError("Cannot find type {type}", type); - return Task.CompletedTask; + _logger.LogWarning("Invalid game event received."); + return; } - IGameEvent? typedEvent = null; - - // If SignalR .NET client gets support for polymorphic json serialization we can - // change the signature of this method to IGameEvent and get rid of this mess. - switch (targetType.Name) + var typedEvent = jsonEvent.Deserialize(JsonSerializerOptions.Web); + if (typedEvent is null) { - case nameof(GameReset): - typedEvent = DeserializeEvent(jsonEvent); - break; - case nameof(PlayerJoinedGame): - typedEvent = DeserializeEvent(jsonEvent); - break; - case nameof(PlayerLeftGame): - typedEvent = DeserializeEvent(jsonEvent); - break; - case nameof(Sync): - typedEvent = DeserializeEvent(jsonEvent); - break; - case nameof(VoteCast): - typedEvent = DeserializeEvent(jsonEvent); - break; - case nameof(VotesShown): - typedEvent = DeserializeEvent(jsonEvent); - break; - default: - _logger.LogError("Cannot handle type {type}", targetType.Name); - break; + _logger.LogWarning("Failed to deserialize game event."); + return; } - + if (typedEvent is PlayerJoinedGame joinedGame) { // Save player details, so we can broadcast a leave event when client disconnects @@ -64,16 +39,11 @@ public Task BroadcastGameEvent(string type, object gameEvent) Context.Items[GameIdItem] = joinedGame.GameId; // Add client to SignalR group so it receives events for the game it joined - Groups.AddToGroupAsync(Context.ConnectionId, joinedGame.GameId); + await Groups.AddToGroupAsync(Context.ConnectionId, joinedGame.GameId); } - if (typedEvent is not null) - { - _logger.LogInformation("{gameId}: processing event {event}", typedEvent.GameId, typedEvent); - return Clients.GroupExcept(typedEvent.GameId, Context.ConnectionId).ReceiveGameEvent(typedEvent); - } - - return Task.CompletedTask; + _logger.LogInformation("{gameId}: processing event {event}", typedEvent.GameId, typedEvent); + await Clients.GroupExcept(typedEvent.GameId, Context.ConnectionId).ReceiveGameEvent(typedEvent); } public override async Task OnConnectedAsync() @@ -97,9 +67,4 @@ public override async Task OnDisconnectedAsync(Exception? exception) await base.OnDisconnectedAsync(exception); } - - private static T? DeserializeEvent(JsonElement jsonEvent) where T : class, IGameEvent - { - return jsonEvent.Deserialize(JsonOptions); - } } diff --git a/PointingParty/PointingParty.csproj b/PointingParty/PointingParty.csproj index 57dc88e..ba484c3 100644 --- a/PointingParty/PointingParty.csproj +++ b/PointingParty/PointingParty.csproj @@ -10,7 +10,7 @@ - + diff --git a/PointingParty/Program.cs b/PointingParty/Program.cs index cf1f27a..2d6a553 100644 --- a/PointingParty/Program.cs +++ b/PointingParty/Program.cs @@ -39,4 +39,4 @@ app.MapHub("/events"); -app.Run(); \ No newline at end of file +app.Run();