mirror of
https://github.com/fluxerapp/fluxer
synced 2026-10-07 19:22:14 +09:00
perf(gateway): skip member list resync on inert presence deltas (#2180)
This commit is contained in:
@@ -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 => #{
|
||||
|
||||
Reference in New Issue
Block a user