perf(gateway): skip member list resync on inert presence deltas (#2180)

This commit is contained in:
Hampus
2026-08-30 23:05:13 +02:00
committed by GitHub
parent 43d6c85f7e
commit 6c9afcc734
2 changed files with 137 additions and 4 deletions
@@ -45,17 +45,55 @@ broadcast_member_list_updates(
_NewPresence
) ->
{ok, UpdatedState};
broadcast_member_list_updates(UserId, OldState, UpdatedState, _OldPresence, _NewPresence) ->
broadcast_member_list_updates(UserId, OldState, UpdatedState, OldPresence, NewPresence) ->
guild_member_list_write_context:with_guild_id(UpdatedState, fun(_GuildId) ->
SubsTab = maps:get(member_list_subscriptions, UpdatedState),
OldMember = find_member_in_state_data(UserId, OldState),
NewMember = find_member_in_state_data(UserId, UpdatedState),
State1 = dispatch_user_change_to_subscribed_lists(
UserId, OldMember, NewMember, SubsTab, UpdatedState
State1 = dispatch_presence_delta(
UserId, OldMember, NewMember, OldPresence, NewPresence, UpdatedState
),
{ok, State1}
end).
-spec dispatch_presence_delta(
user_id(),
map() | undefined,
map() | undefined,
map() | undefined,
map() | undefined,
guild_state()
) -> guild_state().
dispatch_presence_delta(UserId, OldMember, NewMember, OldPresence, NewPresence, State) ->
case presence_delta_is_inert(OldPresence, NewPresence, OldMember, NewMember) of
true ->
State;
false ->
SubsTab = maps:get(member_list_subscriptions, State),
dispatch_user_change_to_subscribed_lists(
UserId, OldMember, NewMember, SubsTab, State
)
end.
-spec presence_delta_is_inert(
map() | undefined,
map() | undefined,
map() | undefined,
map() | undefined
) -> boolean().
presence_delta_is_inert(OldPresence, NewPresence, Member, Member) when
is_map(OldPresence), is_map(NewPresence), is_map(Member)
->
member_list_presence_fields(OldPresence) =:= member_list_presence_fields(NewPresence);
presence_delta_is_inert(_OldPresence, _NewPresence, _OldMember, _NewMember) ->
false.
-spec member_list_presence_fields(map()) -> {binary(), term()}.
member_list_presence_fields(Presence) ->
{
maps:get(<<"status">>, Presence, <<"offline">>),
maps:get(<<"custom_status">>, Presence, null)
}.
-spec find_member_in_state_data(user_id(), guild_state()) -> map() | undefined.
find_member_in_state_data(UserId, State) ->
guild_data_index:get_member(UserId, maps:get(data, State, #{})).
@@ -311,6 +311,101 @@ run_send_member_list_update_encodes_wire_payload() ->
?assert(false)
end.
broadcast_presence_delta_outside_list_payload_skips_sync_test() ->
with_sync_dispatch_mock(fun run_broadcast_presence_delta_outside_list_payload_skips_sync/0).
run_broadcast_presence_delta_outside_list_payload_skips_sync() ->
Ref = guild_member_list_engine:new(),
try
State = presence_delta_state(Ref),
{ok, NewState} = guild_member_list:broadcast_member_list_updates(
1,
State,
State,
presence_map(<<"online">>, false, null),
presence_map(<<"online">>, true, null)
),
?assertEqual(State, NewState),
assert_no_sync_dispatch()
after
guild_member_list_engine:destroy(Ref)
end.
broadcast_status_change_dispatches_sync_test() ->
with_sync_dispatch_mock(fun run_broadcast_status_change_dispatches_sync/0).
run_broadcast_status_change_dispatches_sync() ->
Ref = guild_member_list_engine:new(),
try
State = presence_delta_state(Ref),
{ok, NewState} = guild_member_list:broadcast_member_list_updates(
1,
State,
State,
presence_map(<<"online">>, false, null),
presence_map(<<"idle">>, false, null)
),
assert_single_channel_sync_dispatch(State, NewState),
assert_no_sync_dispatch()
after
guild_member_list_engine:destroy(Ref)
end.
broadcast_custom_status_change_dispatches_sync_test() ->
with_sync_dispatch_mock(fun run_broadcast_custom_status_change_dispatches_sync/0).
run_broadcast_custom_status_change_dispatches_sync() ->
Ref = guild_member_list_engine:new(),
try
State = presence_delta_state(Ref),
{ok, NewState} = guild_member_list:broadcast_member_list_updates(
1,
State,
State,
presence_map(<<"online">>, false, null),
presence_map(<<"online">>, false, #{<<"text">> => <<"hi">>})
),
assert_single_channel_sync_dispatch(State, NewState),
assert_no_sync_dispatch()
after
guild_member_list_engine:destroy(Ref)
end.
broadcast_offline_transition_dispatches_sync_test() ->
with_sync_dispatch_mock(fun run_broadcast_offline_transition_dispatches_sync/0).
run_broadcast_offline_transition_dispatches_sync() ->
Ref = guild_member_list_engine:new(),
try
State = presence_delta_state(Ref),
{ok, NewState} = guild_member_list:broadcast_member_list_updates(
1,
State,
State,
presence_map(<<"online">>, false, null),
presence_map(<<"offline">>, false, null)
),
assert_single_channel_sync_dispatch(State, NewState),
assert_no_sync_dispatch()
after
guild_member_list_engine:destroy(Ref)
end.
presence_delta_state(Ref) ->
Member = #{
<<"user">> => #{<<"id">> => <<"1">>, <<"username">> => <<"one">>},
<<"roles">> => []
},
channel_list_state(Ref, make_subs_tab([{<<"500">>, <<"s1">>, [{0, 99}]}]), [Member]).
presence_map(Status, Mobile, CustomStatus) ->
#{
<<"status">> => Status,
<<"mobile">> => Mobile,
<<"afk">> => false,
<<"custom_status">> => CustomStatus
}.
channel_list_state(Ref, SubsTab, Members) ->
(base_state(SubsTab))#{
data => #{