Mirrors prod's TK2 wire flow: the first arriver (parked, picks up cached pair on a later poll) gets matching_state 3007 (SUCCEEDED_OWNER); the second arriver (whose poll triggered the pair) gets 3004 (SUCCEEDED). Observationally inert in the public matching code path today — the client's Matching class writes isOwner from the response into a field that nothing in TK2/ranked reads. Matching_Room (private rooms) DOES read it but from a separate code path that doesn't consult our response. We send the split anyway for prod fidelity and to leave room for future flows (rematch UI, etc.) that might start consuming it. TryPairAsync now returns PairUpResult(Match, IsOwner) instead of bare PendingMatch?, so the controller can decide owner vs joiner without re-deriving it. Also documents on DoMatchingResponseDto why we omit prod's `room_id` field (not in the client's DoMatchingDetail model; private-room flows get their room id from a different API and don't consult this response). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
39 lines
1.7 KiB
C#
39 lines
1.7 KiB
C#
using SVSim.BattleNode.Bridge;
|
|
|
|
namespace SVSim.EmulatedEntrypoint.Matching;
|
|
|
|
/// <summary>
|
|
/// Minimal in-process matching queue stand-in. The proper queue API is a separate
|
|
/// spec; this is enough to actually pair two viewers polling /do_matching on the
|
|
/// same mode.
|
|
/// </summary>
|
|
public interface IMatchingPairUpService
|
|
{
|
|
/// <summary>
|
|
/// Try to pair the calling viewer with an already-waiting partner.
|
|
/// Returns the resolved <see cref="PairUpResult"/> when a partner was found
|
|
/// (either this call paired with a waiter, or a previous pairing's result is
|
|
/// still cached for this viewer). Returns null if this viewer is the first
|
|
/// arriver and should be parked (caller returns 3002 RETRY).
|
|
/// </summary>
|
|
Task<PairUpResult?> TryPairAsync(string mode, BattlePlayer player, CancellationToken ct);
|
|
}
|
|
|
|
/// <summary>
|
|
/// A resolved pair-up for a single caller.
|
|
/// <para>
|
|
/// <see cref="IsOwner"/> distinguishes the "original waiter" (first arriver, whose
|
|
/// cached result is being consumed on a follow-up poll — maps to wire matching_state
|
|
/// 3007 = RC_BATTLE_MATCHING_SUCCEEDED_OWNER) from the "joiner" (second arriver,
|
|
/// whose poll triggered the pair — maps to 3004 = RC_BATTLE_MATCHING_SUCCEEDED).
|
|
/// </para>
|
|
/// <para>
|
|
/// The split mirrors prod's TK2 wire flow (waiter sees 3007, joiner sees 3004) but
|
|
/// is observationally inert in the public-matching code path: the client's
|
|
/// <c>Matching</c> class writes <c>isOwner</c> from the response into a field that
|
|
/// nothing else in TK2/ranked reads. We send the split anyway for prod fidelity in
|
|
/// case a future flow (rematch UI, private rooms grafted on top) starts consuming it.
|
|
/// </para>
|
|
/// </summary>
|
|
public sealed record PairUpResult(PendingMatch Match, bool IsOwner);
|