game removal code cleanup

This commit is contained in:
jheaps
2025-10-03 11:24:02 -06:00
parent 54e4f25be7
commit 03dd308449
+35 -33
View File
@@ -18,8 +18,12 @@ public class ChessController(
/// Store of ongoing games. /// Store of ongoing games.
/// </summary> /// </summary>
private static readonly ConcurrentDictionary<Guid, GameState> _games = []; private static readonly ConcurrentDictionary<Guid, GameState> _games = [];
private static readonly ConcurrentDictionary<Guid, Task> _gameRemovalTasks = [];
private static readonly ConcurrentDictionary<Guid, CancellationTokenSource> _gameRemovalCancellationTokens = [];
private static ConcurrentDictionary<Guid, Task> _gameRemovalTasks = []; private static readonly TimeSpan _computerGameTimeout = TimeSpan.FromHours(1);
private static readonly TimeSpan _multiplayerGameTimeout = TimeSpan.FromSeconds(5);
private static readonly TimeSpan _gameCleanupTimeout = TimeSpan.FromMinutes(1);
/// <summary> /// <summary>
/// Create a new chess game and store it in-memory. /// Create a new chess game and store it in-memory.
@@ -57,7 +61,7 @@ public class ChessController(
}); });
} }
ScheduleRemoveGame(gameState.GameId, TimeSpan.FromHours(1)); ScheduleRemoveGame(gameState.GameId, _computerGameTimeout);
return Ok(new return Ok(new
{ {
@@ -99,7 +103,7 @@ public class ChessController(
isWhite = false; isWhite = false;
} }
ScheduleRemoveGame(gameState.GameId, TimeSpan.FromDays(1)); ScheduleRemoveGame(gameState.GameId, _multiplayerGameTimeout);
return Ok(new return Ok(new
{ {
@@ -178,18 +182,11 @@ public class ChessController(
return BadRequest(result); return BadRequest(result);
if (result.IsCheckmate || result.IsStalemate) if (result.IsCheckmate || result.IsStalemate)
{ ScheduleRemoveGame(gameState.GameId, _gameCleanupTimeout);
// queue game removal else if (gameState.IsVsComputer)
ScheduleRemoveGame(gameState.GameId, TimeSpan.FromMinutes(1)); ScheduleRemoveGame(gameState.GameId, _computerGameTimeout);
}
else else
{ ScheduleRemoveGame(gameState.GameId, _multiplayerGameTimeout);
// increase timeout if play continues.
if (gameState.IsVsComputer)
ScheduleRemoveGame(gameState.GameId, TimeSpan.FromHours(1));
else
ScheduleRemoveGame(gameState.GameId, TimeSpan.FromDays(1));
}
if (gameState.IsVsComputer && gameState.Computer is not null) if (gameState.IsVsComputer && gameState.Computer is not null)
queue.Queue(() => gameState.Computer.MakeMove(gameState, chessHub, chessService)); queue.Queue(() => gameState.Computer.MakeMove(gameState, chessHub, chessService));
@@ -232,31 +229,36 @@ public class ChessController(
private static void ScheduleRemoveGame(Guid id, TimeSpan delay) private static void ScheduleRemoveGame(Guid id, TimeSpan delay)
{ {
if (_gameRemovalTasks.ContainsKey(id)) if (_gameRemovalCancellationTokens.TryRemove(id, out var oldCts))
{ {
oldCts.Cancel();
oldCts.Dispose();
}
var cts = new CancellationTokenSource();
_gameRemovalCancellationTokens[id] = cts;
_gameRemovalTasks[id] = Task.Run(async () => _gameRemovalTasks[id] = Task.Run(async () =>
{ {
await Task.Delay(delay); try
if (_games[id].Computer is not null)
await _games[id].Computer!.DisposeAsync();
_games.Remove(id, out _);
_gameRemovalTasks.Remove(id, out _);
});
return;
}
_gameRemovalTasks.TryAdd(id, Task.Run(async () =>
{ {
await Task.Delay(delay); await Task.Delay(delay, cts.Token);
if (_games[id].Computer is not null) if (_games.TryGetValue(id, out var game) && game.Computer is not null)
await _games[id].Computer!.DisposeAsync(); await game.Computer.DisposeAsync();
_games.Remove(id, out _); _games.Remove(id, out _);
_gameRemovalTasks.Remove(id, out _); }
})); catch (OperationCanceledException) { }
finally
{
if (_gameRemovalCancellationTokens.TryGetValue(id, out var currentCts) && currentCts == cts)
{
_gameRemovalCancellationTokens.TryRemove(id, out _);
}
cts.Dispose();
}
});
} }
} }