using SVSim.BattleNode.Protocol; namespace SVSim.BattleNode.Reliability; /// /// Per-session outbound ledger. Assigns monotonic playSeq to ordered pushes and archives /// them for future Resume retransmit (v2). No-stock control pushes (BattleFinish/JudgeResult/Resume) /// are wrapped with no playSeq and skip the archive. /// public sealed class OutboundSequencer { private long _next = 1; private readonly Dictionary _archive = new(); public IReadOnlyDictionary Archive => _archive; public MsgEnvelope AssignAndArchive(MsgEnvelope envelope) { var seq = _next++; var stamped = envelope with { PlaySeq = seq }; _archive[seq] = stamped; return stamped; } public MsgEnvelope WrapNoStock(MsgEnvelope envelope) => envelope with { PlaySeq = null }; /// /// Drop all archived envelopes. Called from BattleSession's terminate cascade so /// the archive — the heavy state — is released the moment the battle ends, rather /// than waiting for the participant to be GC'd. _next is left untouched: /// a participant emitting after Clear is a bug, not a recovery case, but the seq /// stream stays monotonic so a stray emit doesn't silently re-use a playSeq value. /// public void Clear() => _archive.Clear(); }