Use IHubContext for delayed slip completion
Some checks failed
Build / build (push) Has been cancelled

Avoid ObjectDisposedException when sending SignalR updates after the
30-second delay by accessing clients through IHubContext instead of
the disposed hub instance.

Signed-off-by: Tim Krampitz <Tim.Krampitz@live.com>
This commit is contained in:
Tim Krampitz
2026-10-04 21:58:23 +02:00
parent 88e08544c6
commit 8bccf66e84
2 changed files with 16 additions and 4 deletions

View File

@@ -24,6 +24,8 @@ public class GameHubTests
private readonly Mock<ISingleClientProxy> _callerProxy = new(); private readonly Mock<ISingleClientProxy> _callerProxy = new();
private readonly Mock<IClientProxy> _groupProxy = new(); private readonly Mock<IClientProxy> _groupProxy = new();
private readonly Mock<ISingleClientProxy> _clientProxy = new(); private readonly Mock<ISingleClientProxy> _clientProxy = new();
private readonly Mock<IHubContext<GameHub>> _hubContext = new();
private readonly Mock<IHubClients> _hubClients = new();
private readonly GameHub _hub; private readonly GameHub _hub;
private const string ConnectionId = "test-connection-id"; private const string ConnectionId = "test-connection-id";
@@ -35,7 +37,11 @@ public class GameHubTests
_clients.Setup(c => c.Group(It.IsAny<string>())).Returns(_groupProxy.Object); _clients.Setup(c => c.Group(It.IsAny<string>())).Returns(_groupProxy.Object);
_clients.Setup(c => c.Client(It.IsAny<string>())).Returns(_clientProxy.Object); _clients.Setup(c => c.Client(It.IsAny<string>())).Returns(_clientProxy.Object);
_hub = new GameHub(_gameService.Object, _factory, NullLogger<GameHub>.Instance); _hubClients.Setup(c => c.Group(It.IsAny<string>())).Returns(_groupProxy.Object);
_hubClients.Setup(c => c.Client(It.IsAny<string>())).Returns(_clientProxy.Object);
_hubContext.Setup(c => c.Clients).Returns(_hubClients.Object);
_hub = new GameHub(_gameService.Object, _factory, NullLogger<GameHub>.Instance, _hubContext.Object);
SetupContext(); SetupContext();
} }

View File

@@ -14,12 +14,18 @@ public class GameHub : Hub
private readonly IGameService _gameService; private readonly IGameService _gameService;
private readonly IDbContextFactory<SlipItInDbContext> _contextFactory; private readonly IDbContextFactory<SlipItInDbContext> _contextFactory;
private readonly ILogger<GameHub> _logger; private readonly ILogger<GameHub> _logger;
private readonly IHubContext<GameHub> _hubContext;
public GameHub(IGameService gameService, IDbContextFactory<SlipItInDbContext> contextFactory, ILogger<GameHub> logger) public GameHub(
IGameService gameService,
IDbContextFactory<SlipItInDbContext> contextFactory,
ILogger<GameHub> logger,
IHubContext<GameHub> hubContext)
{ {
_gameService = gameService; _gameService = gameService;
_contextFactory = contextFactory; _contextFactory = contextFactory;
_logger = logger; _logger = logger;
_hubContext = hubContext;
} }
/// <summary> /// <summary>
@@ -260,10 +266,10 @@ public class GameHub : Hub
var targetP = await db.Players.FindAsync(playerId); var targetP = await db.Players.FindAsync(playerId);
if (targetP?.ConnectionId != null) if (targetP?.ConnectionId != null)
{ {
await Clients.Client(targetP.ConnectionId).SendAsync("PlayerHandUpdated", updatedHand); await _hubContext.Clients.Client(targetP.ConnectionId).SendAsync("PlayerHandUpdated", updatedHand);
} }
await Clients.Group(game.LobbyCode).SendAsync("GameStateUpdated", updatedGameState); await _hubContext.Clients.Group(game.LobbyCode).SendAsync("GameStateUpdated", updatedGameState);
} }
} }
catch (Exception ex) catch (Exception ex)