fix(gateway): clamp a heartbeat ack to the session sequence (#2283)

This commit is contained in:
Hampus
2026-08-31 22:23:43 +02:00
committed by GitHub
parent 4261cc2ea5
commit be3e12e60d
2 changed files with 15 additions and 2 deletions
@@ -280,13 +280,14 @@ handle_is_staff(State) ->
handle_heartbeat_ack(Seq, #{ack_seq := AckSeq} = State) when Seq < AckSeq ->
{reply, true, State};
handle_heartbeat_ack(Seq, #{buffer := Buffer} = State) ->
NewBuffer = drop_acked_buffer(Seq, Buffer),
AckedSeq = min(Seq, maps:get(seq, State, Seq)),
NewBuffer = drop_acked_buffer(AckedSeq, Buffer),
NewBytes =
case is_list(NewBuffer) of
true -> session_init:replay_buffer_bytes(NewBuffer);
false -> limited_deque:bytes(NewBuffer)
end,
NewState0 = State#{ack_seq => Seq, buffer => NewBuffer, buffer_bytes => NewBytes},
NewState0 = State#{ack_seq => AckedSeq, buffer => NewBuffer, buffer_bytes => NewBytes},
NewState = session_connection_guild:repair_stalled_guild_connects(NewState0),
{reply, true, NewState}.
@@ -151,6 +151,18 @@ heartbeat_ack_tolerates_backwards_ack_without_trimming_test() ->
?assertEqual(5, maps:get(ack_seq, State1)),
?assertEqual([Event], maps:get(buffer, State1)).
heartbeat_ack_clamps_ack_seq_to_current_seq_test() ->
State0 = resume_test_state(#{
seq => 5,
ack_seq => 0,
buffer => [#{seq => 5, event => message_create, data => #{}}]
}),
{reply, true, State1} = session_lifecycle:handle_heartbeat_ack(1000000, State0),
?assertEqual(5, maps:get(ack_seq, State1)),
?assertMatch(
{reply, {ok, [], 5}, _}, session_lifecycle:handle_resume(5, self(), State1)
).
handle_resume_clamps_truncated_gap_in_replay_buffer_test() ->
State0 = resume_test_state(#{
seq => 5,