feat(battle-node): WaitingRoom for PvP WS rendezvous
Per-BattleId slot keyed dict. Pair returns the first arriver to the second; ParkAsync awaits a TCS and returns the second arriver. Timeout defaults to BattleNodeOptions.WaitingRoomTimeout (60s); evict on timeout keeps the dict clean. Singleton in DI; consumed by the handler in the next task.
This commit is contained in:
26
SVSim.BattleNode/Hosting/IWaitingRoom.cs
Normal file
26
SVSim.BattleNode/Hosting/IWaitingRoom.cs
Normal file
@@ -0,0 +1,26 @@
|
||||
using SVSim.BattleNode.Sessions.Participants;
|
||||
|
||||
namespace SVSim.BattleNode.Hosting;
|
||||
|
||||
/// <summary>
|
||||
/// Per-BattleId WS rendezvous for PvP. First arriver parks; second arriver pairs.
|
||||
/// The handler reads the result and either constructs the session (second arriver)
|
||||
/// or awaits termination via the participant's session-finished signal (first arriver).
|
||||
/// </summary>
|
||||
public interface IWaitingRoom
|
||||
{
|
||||
/// <summary>Try to claim a previously-parked first arriver. Returns the first
|
||||
/// arriver (and clears the slot) if one is parked; null if this caller is the
|
||||
/// first arriver (caller should then ParkAsync).</summary>
|
||||
RealParticipant? Pair(string battleId, RealParticipant self);
|
||||
|
||||
/// <summary>Park as the first arriver; await pairing or timeout. Returns the
|
||||
/// second arriver on pairing; null on timeout / cancellation / TryAdd race.</summary>
|
||||
Task<RealParticipant?> ParkAsync(string battleId, RealParticipant self,
|
||||
TimeSpan timeout, CancellationToken ct);
|
||||
|
||||
/// <summary>Best-effort cleanup; idempotent. Called on timeout or cancellation
|
||||
/// so a stale TCS doesn't linger if the first arriver disconnects before
|
||||
/// pairing.</summary>
|
||||
void Evict(string battleId);
|
||||
}
|
||||
Reference in New Issue
Block a user