mirror of
https://github.com/fluxerapp/fluxer
synced 2026-10-07 19:22:14 +09:00
perf(gateway): speed up presence and harden guild queries (#3072)
This commit is contained in:
@@ -118,6 +118,7 @@ init_guilds_role_includes_only_guild_state_children_test() ->
|
||||
?assert(lists:member(presence_bus, Ids)),
|
||||
?assert(lists:member(guild_manager, Ids)),
|
||||
?assert(lists:member(guild_counts_cache, Ids)),
|
||||
?assert(lists:member(gateway_clock_offset, Ids)),
|
||||
?assert(lists:member(voice_state_counts_sync, Ids)),
|
||||
?assert(lists:member(gateway_cluster_handoff, Ids)),
|
||||
?assertNot(lists:member(session_manager, Ids)),
|
||||
@@ -137,6 +138,7 @@ init_sessions_role_includes_cluster_handoff_test() ->
|
||||
?assert(lists:member(session_state_transfer, Ids)),
|
||||
?assert(lists:member(gateway_cluster_handoff, Ids)),
|
||||
?assertNot(lists:member(guild_manager, Ids)),
|
||||
?assertNot(lists:member(gateway_clock_offset, Ids)),
|
||||
?assertNot(lists:member(presence_manager, Ids)),
|
||||
persistent_term:erase({fluxer_gateway, runtime_config}).
|
||||
|
||||
|
||||
@@ -5,6 +5,124 @@
|
||||
|
||||
-include_lib("eunit/include/eunit.hrl").
|
||||
|
||||
read_model_preserves_query_results_test() ->
|
||||
State = read_model_state(),
|
||||
try
|
||||
ok = guild_read_model:put_state(State),
|
||||
lists:foreach(
|
||||
fun({Tag, Request, Handler}) ->
|
||||
{reply, Expected, _} = Handler(Request, State),
|
||||
?assertEqual({ok, Expected}, guild_read_model:query(100, {Tag, Request}))
|
||||
end,
|
||||
[
|
||||
{get_guild_data, #{user_id => 200}, fun guild_data:get_guild_data/2},
|
||||
{get_guild_data, #{user_id => 999}, fun guild_data:get_guild_data/2},
|
||||
{get_guild_data, #{user_id => null}, fun guild_data:get_guild_data/2},
|
||||
{get_guild_auth_context, #{user_id => 200, channel_id => 500},
|
||||
fun guild_data:get_auth_context/2},
|
||||
{get_guild_auth_context, #{user_id => 999, channel_id => null},
|
||||
fun guild_data:get_auth_context/2},
|
||||
{get_guild_member, #{user_id => 200}, fun guild_data:get_guild_member/2},
|
||||
{get_guild_member, #{user_id => 999}, fun guild_data:get_guild_member/2},
|
||||
{has_member, #{user_id => 200}, fun guild_data:has_member/2}
|
||||
]
|
||||
)
|
||||
after
|
||||
cleanup_read_model(State)
|
||||
end.
|
||||
|
||||
read_model_uses_live_member_rows_without_copying_members_test() ->
|
||||
State = read_model_state(),
|
||||
#{data := #{members_ets := Tab}} = State,
|
||||
try
|
||||
ok = guild_read_model:put_state(State),
|
||||
[{100, _, #{data := SnapshotData}}] = ets:lookup(guild_read_model, 100),
|
||||
?assertEqual(#{}, maps:get(<<"members">>, SnapshotData)),
|
||||
[{200, Member}] = ets:lookup(Tab, 200),
|
||||
Updated = Member#{
|
||||
<<"nick">> => <<"new nickname">>, <<"communication_disabled_until">> => null
|
||||
},
|
||||
ets:insert(Tab, {200, Updated}),
|
||||
?assertEqual(
|
||||
{ok, #{success => true, member_data => Updated}},
|
||||
guild_read_model:query(100, {get_guild_member, #{user_id => 200}})
|
||||
),
|
||||
ets:delete(Tab, 200),
|
||||
?assertEqual(
|
||||
{ok, #{has_member => false}},
|
||||
guild_read_model:query(100, {has_member, #{user_id => 200}})
|
||||
),
|
||||
?assertMatch(
|
||||
{ok, #{guild_data := null}},
|
||||
guild_read_model:query(100, {get_guild_data, #{user_id => 200}})
|
||||
)
|
||||
after
|
||||
cleanup_read_model(State)
|
||||
end.
|
||||
|
||||
read_model_observes_role_and_collection_changes_test() ->
|
||||
State = read_model_state(),
|
||||
try
|
||||
ok = guild_read_model:put_state(State),
|
||||
Data = maps:get(data, State),
|
||||
UpdatedData = guild_data_index:normalize_map(Data#{
|
||||
<<"roles">> => [#{<<"id">> => 100, <<"permissions">> => 0}],
|
||||
<<"emojis">> => [#{<<"id">> => 700, <<"name">> => <<"new">>}]
|
||||
}),
|
||||
Updated = State#{data => UpdatedData},
|
||||
ok = guild_read_model:update(State, Updated),
|
||||
{reply, Expected, _} = guild_data:get_guild_data(#{user_id => 200}, Updated),
|
||||
?assertEqual(
|
||||
{ok, Expected}, guild_read_model:query(100, {get_guild_data, #{user_id => 200}})
|
||||
),
|
||||
#{guild_data := GuildData} = Expected,
|
||||
?assertEqual([], maps:get(<<"channels">>, GuildData))
|
||||
after
|
||||
cleanup_read_model(State)
|
||||
end.
|
||||
|
||||
read_model_survives_blocked_owner_and_rejects_dead_tables_test() ->
|
||||
State = read_model_state(),
|
||||
Self = self(),
|
||||
Owner = spawn(fun() ->
|
||||
ok = guild_read_model:put_state(State),
|
||||
Self ! published,
|
||||
receive
|
||||
stop -> ok
|
||||
end
|
||||
end),
|
||||
try
|
||||
receive
|
||||
published -> ok
|
||||
after 1000 -> error(publish_timeout)
|
||||
end,
|
||||
?assertMatch(
|
||||
{ok, #{auth_context := #{}}},
|
||||
guild_read_model:query(
|
||||
100, {get_guild_auth_context, #{user_id => 200, channel_id => 500}}
|
||||
)
|
||||
),
|
||||
?assertEqual({message_queue_len, 0}, process_info(Owner, message_queue_len)),
|
||||
ets:delete(maps:get(members_ets, maps:get(data, State))),
|
||||
?assertEqual(miss, guild_read_model:query(100, {has_member, #{user_id => 200}}))
|
||||
after
|
||||
Owner ! stop,
|
||||
cleanup_read_model(State)
|
||||
end.
|
||||
|
||||
read_model_state() ->
|
||||
State = test_state(),
|
||||
Data = guild_data_index:normalize_map(maps:get(data, State)),
|
||||
Members = guild_data_index:member_map(Data),
|
||||
Tab = ets:new(read_model_members, [set, public]),
|
||||
ets:insert(Tab, maps:to_list(Members)),
|
||||
State#{member_count => map_size(Members), data => Data#{members_ets => Tab}}.
|
||||
|
||||
cleanup_read_model(#{data := Data} = State) ->
|
||||
guild_read_model:delete(100),
|
||||
catch ets:delete(maps:get(members_ets, Data)),
|
||||
ets:delete(maps:get(member_presence, State)).
|
||||
|
||||
get_guild_data_membership_gate_test() ->
|
||||
State = test_state(),
|
||||
{reply, Reply1, _} = guild_data:get_guild_data(#{user_id => 999}, State),
|
||||
|
||||
@@ -551,3 +551,53 @@ engine_roles_for_test_member(UserId) when UserId rem 5 =:= 0 ->
|
||||
[20];
|
||||
engine_roles_for_test_member(_UserId) ->
|
||||
[].
|
||||
|
||||
version_bumps_on_every_mutation_test() ->
|
||||
Ref = guild_member_list_engine:new(),
|
||||
try
|
||||
V0 = guild_member_list_engine:version(Ref),
|
||||
ok = guild_member_list_engine:bulk_load(Ref, [{1, <<"a">>, [], true}], []),
|
||||
V1 = guild_member_list_engine:version(Ref),
|
||||
ok = guild_member_list_engine:add_member(Ref, 2, <<"b">>, [], false),
|
||||
V2 = guild_member_list_engine:version(Ref),
|
||||
ok = guild_member_list_engine:update_member(Ref, 2, <<"c">>, [], false),
|
||||
V3 = guild_member_list_engine:version(Ref),
|
||||
ok = guild_member_list_engine:set_online(Ref, 2, true),
|
||||
V4 = guild_member_list_engine:version(Ref),
|
||||
changed = guild_member_list_engine:set_hoisted_roles(Ref, [7]),
|
||||
V5 = guild_member_list_engine:version(Ref),
|
||||
ok = guild_member_list_engine:remove_member(Ref, 1),
|
||||
V6 = guild_member_list_engine:version(Ref),
|
||||
Versions = [V0, V1, V2, V3, V4, V5, V6],
|
||||
?assertEqual(Versions, lists:usort(Versions)),
|
||||
?assertEqual(7, length(lists:usort(Versions)))
|
||||
after
|
||||
guild_member_list_engine:destroy(Ref)
|
||||
end.
|
||||
|
||||
version_is_stable_for_noop_mutations_test() ->
|
||||
Ref = guild_member_list_engine:new(),
|
||||
try
|
||||
ok = guild_member_list_engine:add_member(Ref, 1, <<"a">>, [], true),
|
||||
V = guild_member_list_engine:version(Ref),
|
||||
ok = guild_member_list_engine:set_online(Ref, 1, true),
|
||||
ok = guild_member_list_engine:set_online(Ref, 99, false),
|
||||
ok = guild_member_list_engine:remove_member(Ref, 99),
|
||||
unchanged = guild_member_list_engine:set_hoisted_roles(Ref, []),
|
||||
_ = guild_member_list_engine:get_items(Ref, 0, 10),
|
||||
?assertEqual(V, guild_member_list_engine:version(Ref))
|
||||
after
|
||||
guild_member_list_engine:destroy(Ref)
|
||||
end.
|
||||
|
||||
version_survives_tables_without_a_version_row_test() ->
|
||||
Ref = guild_member_list_engine:new(),
|
||||
try
|
||||
true = ets:delete(Ref, version),
|
||||
?assertEqual(undefined, guild_member_list_engine:version(Ref)),
|
||||
ok = guild_member_list_engine:add_member(Ref, 1, <<"a">>, [], true),
|
||||
?assertEqual(1, guild_member_list_engine:version(Ref))
|
||||
after
|
||||
guild_member_list_engine:destroy(Ref)
|
||||
end,
|
||||
?assertEqual(undefined, guild_member_list_engine:version(Ref)).
|
||||
|
||||
Reference in New Issue
Block a user