refactor(battle-node): cut handler over to BattleSessionV2 + participants
Production WS path now constructs RealParticipant + ScriptedBotParticipant and hands them to BattleSessionV2 instead of the old single-WS BattleSession. Wire behaviour preserved end-to-end (BattleNodeFlowTests still pass). Also fixes a RunAsync bug uncovered by the cutover: WhenAny would terminate the session as soon as the scripted bot's no-op RunAsync resolved, killing the live WS read loop before any traffic arrived. Phase 1 semantics are simpler — wait for ALL participants. Phase 2's Pvp disconnect propagation will revisit this.
This commit is contained in:
@@ -42,13 +42,13 @@ public sealed class BattleSessionV2
|
||||
|
||||
public async Task RunAsync(CancellationToken cancellation)
|
||||
{
|
||||
// Run both participants' inbound loops in parallel. First to complete cancels
|
||||
// the session via the outer cancellation token.
|
||||
using var cts = CancellationTokenSource.CreateLinkedTokenSource(cancellation);
|
||||
var aTask = A.RunAsync(cts.Token);
|
||||
var bTask = B.RunAsync(cts.Token);
|
||||
await Task.WhenAny(aTask, bTask);
|
||||
cts.Cancel();
|
||||
// Run both participants' inbound loops in parallel and wait for them all to
|
||||
// complete. NoOp/Scripted bots return immediately; Real returns when the WS
|
||||
// closes. Using WhenAny here would have killed the session as soon as the
|
||||
// scripted bot's no-op RunAsync resolved. Phase 2's Pvp/Bot cases will need
|
||||
// disconnect propagation; that's wired in their own task.
|
||||
var aTask = A.RunAsync(cancellation);
|
||||
var bTask = B.RunAsync(cancellation);
|
||||
try { await Task.WhenAll(aTask, bTask); } catch { /* swallow cancellation */ }
|
||||
|
||||
await Task.WhenAll(
|
||||
|
||||
Reference in New Issue
Block a user