mirror of
https://github.com/fluxerapp/fluxer
synced 2026-10-17 21:15:32 +09:00
refactor(gateway): share shard helpers and test fixtures (#3381)
This commit is contained in:
1 parent
f22261f218
commit
e7b13fd19f
25 files changed
+101
-2021
No files matched your search
@@ -153,26 +153,12 @@ select_shard(Key, Count) when Count > 0 ->
|
||||
-spec find_shard_by_ref(reference(), #{non_neg_integer() => shard()}) ->
|
||||
{ok, non_neg_integer()} | not_found.
|
||||
find_shard_by_ref(Ref, Shards) ->
|
||||
maps:fold(
|
||||
fun
|
||||
(Index, #{ref := R}, _) when R =:= Ref -> {ok, Index};
|
||||
(_, _, Acc) -> Acc
|
||||
end,
|
||||
not_found,
|
||||
Shards
|
||||
).
|
||||
shard_utils:find_shard_by_ref(Ref, Shards).
|
||||
|
||||
-spec find_shard_by_pid(pid(), #{non_neg_integer() => shard()}) ->
|
||||
{ok, non_neg_integer()} | not_found.
|
||||
find_shard_by_pid(Pid, Shards) ->
|
||||
maps:fold(
|
||||
fun
|
||||
(Index, #{pid := P}, _) when P =:= Pid -> {ok, Index};
|
||||
(_, _, Acc) -> Acc
|
||||
end,
|
||||
not_found,
|
||||
Shards
|
||||
).
|
||||
shard_utils:find_shard_by_pid(Pid, Shards).
|
||||
|
||||
-spec rebalance_retry_timer_ref(map()) -> reference() | undefined.
|
||||
rebalance_retry_timer_ref(State) ->
|
||||
|
||||
@@ -25,19 +25,11 @@
|
||||
|
||||
-spec determine_shard_count() -> {pos_integer(), configured | auto}.
|
||||
determine_shard_count() ->
|
||||
case fluxer_gateway_env:get(guild_shards) of
|
||||
Value when is_integer(Value), Value > 0 ->
|
||||
{Value, configured};
|
||||
_ ->
|
||||
{default_shard_count(), auto}
|
||||
end.
|
||||
shard_utils:determine_shard_count(guild_shards).
|
||||
|
||||
-spec default_shard_count() -> pos_integer().
|
||||
default_shard_count() ->
|
||||
shard_utils:max_positive([
|
||||
erlang:system_info(logical_processors_available),
|
||||
erlang:system_info(schedulers_online)
|
||||
]).
|
||||
clustered_ets_cache:default_shard_count().
|
||||
|
||||
-spec start_shards(pos_integer()) -> #{non_neg_integer() => shard_map()}.
|
||||
start_shards(Count) ->
|
||||
@@ -109,12 +101,12 @@ normalize_grouped_ids(Groups) ->
|
||||
-spec find_shard_by_ref(reference(), #{non_neg_integer() => shard_map()}) ->
|
||||
{ok, non_neg_integer()} | not_found.
|
||||
find_shard_by_ref(Ref, Shards) ->
|
||||
find_shard_by(fun(#{ref := R}) -> R =:= Ref end, Shards).
|
||||
shard_utils:find_shard_by_ref(Ref, Shards).
|
||||
|
||||
-spec find_shard_by_pid(pid(), #{non_neg_integer() => shard_map()}) ->
|
||||
{ok, non_neg_integer()} | not_found.
|
||||
find_shard_by_pid(Pid, Shards) ->
|
||||
find_shard_by(fun(#{pid := P}) -> P =:= Pid end, Shards).
|
||||
shard_utils:find_shard_by_pid(Pid, Shards).
|
||||
|
||||
-spec start_shard_into_map(non_neg_integer(), #{non_neg_integer() => shard_map()}) ->
|
||||
#{non_neg_integer() => shard_map()}.
|
||||
@@ -132,26 +124,3 @@ ensure_live_shard(Index, Pid, State) ->
|
||||
false ->
|
||||
restart_shard_or_fail(Index, State)
|
||||
end.
|
||||
|
||||
-spec find_shard_by(fun((shard_map()) -> boolean()), #{non_neg_integer() => shard_map()}) ->
|
||||
{ok, non_neg_integer()} | not_found.
|
||||
find_shard_by(Pred, Shards) ->
|
||||
maps:fold(
|
||||
fun(Index, ShardMap, Acc) -> find_matching_shard(Pred, Index, ShardMap, Acc) end,
|
||||
not_found,
|
||||
Shards
|
||||
).
|
||||
|
||||
-spec find_matching_shard(
|
||||
fun((shard_map()) -> boolean()),
|
||||
non_neg_integer(),
|
||||
shard_map(),
|
||||
{ok, non_neg_integer()} | not_found
|
||||
) -> {ok, non_neg_integer()} | not_found.
|
||||
find_matching_shard(_Pred, _Index, _ShardMap, {ok, _Found} = Acc) ->
|
||||
Acc;
|
||||
find_matching_shard(Pred, Index, ShardMap, not_found) ->
|
||||
case Pred(ShardMap) of
|
||||
true -> {ok, Index};
|
||||
false -> not_found
|
||||
end.
|
||||
@@ -323,7 +323,7 @@ maybe_add_last_message_id(RawId, RawMsgId, UserId, Member, State, Acc) ->
|
||||
binary(), binary(), term(), integer(), map(), guild_state(), map()
|
||||
) -> map().
|
||||
maybe_add_last_message_for_channel(IdBin, MsgIdBin, RawId, UserId, Member, State, Acc) ->
|
||||
case parse_snowflake(<<"id">>, RawId) of
|
||||
case guild_dispatch_decorate:parse_snowflake(<<"id">>, RawId) of
|
||||
ChId when is_integer(ChId) ->
|
||||
maybe_add_visible_last_message(IdBin, MsgIdBin, UserId, ChId, Member, State, Acc);
|
||||
undefined ->
|
||||
@@ -345,13 +345,6 @@ maybe_add_visible_last_message(IdBin, MsgId, UserId, ChId, Member, State, Acc) -
|
||||
compute_voice_state_updates(Current, Previous, GuildId) ->
|
||||
guild_passive_sync_voice:compute_voice_state_updates(Current, Previous, GuildId).
|
||||
|
||||
-spec parse_snowflake(binary(), term()) -> integer() | undefined.
|
||||
parse_snowflake(FieldName, Value) ->
|
||||
case validation:validate_snowflake(FieldName, Value) of
|
||||
{ok, Id} -> Id;
|
||||
{error, _, _} -> undefined
|
||||
end.
|
||||
|
||||
-spec snowflake_binary(binary(), term()) -> binary() | undefined.
|
||||
snowflake_binary(FieldName, Value) ->
|
||||
case validation:validate_snowflake(FieldName, Value) of
|
||||
|
||||
@@ -150,7 +150,7 @@ moderator_rules_test() ->
|
||||
).
|
||||
|
||||
shared_case_table_test() ->
|
||||
{ok, Contents} = file:read_file("test/thread_permission_cases.json"),
|
||||
{ok, Contents} = file:read_file("../packages/constants/src/ThreadPermissionCases.json"),
|
||||
Cases = [
|
||||
Case
|
||||
|| #{<<"fn">> := Fn} = Case <- json:decode(Contents),
|
||||
|
||||
@@ -39,7 +39,7 @@ ensure_tables() ->
|
||||
-spec upsert_voice_state(voice_state()) -> ok.
|
||||
upsert_voice_state(VoiceState) when is_map(VoiceState) ->
|
||||
ensure_tables(),
|
||||
ConnectionId = normalize_optional_binary(
|
||||
ConnectionId = guild_voice_connection_normalize:normalize_optional_binary(
|
||||
get_optional_field(VoiceState, <<"connection_id">>, connection_id)
|
||||
),
|
||||
upsert_by_connection(ConnectionId, VoiceState);
|
||||
@@ -51,17 +51,17 @@ upsert_by_connection(undefined, _VoiceState) ->
|
||||
ok;
|
||||
upsert_by_connection(ConnectionId, VoiceState) ->
|
||||
case
|
||||
normalize_optional_binary(
|
||||
guild_voice_connection_normalize:normalize_optional_binary(
|
||||
get_optional_field(VoiceState, <<"channel_id">>, channel_id, null)
|
||||
)
|
||||
of
|
||||
undefined ->
|
||||
remove_connection(ConnectionId);
|
||||
_ChannelId ->
|
||||
RegionId = normalize_optional_binary(
|
||||
RegionId = guild_voice_connection_normalize:normalize_optional_binary(
|
||||
get_optional_field(VoiceState, <<"region_id">>, region_id)
|
||||
),
|
||||
ServerId = normalize_optional_binary(
|
||||
ServerId = guild_voice_connection_normalize:normalize_optional_binary(
|
||||
get_optional_field(VoiceState, <<"server_id">>, server_id)
|
||||
),
|
||||
upsert_connection_metadata(ConnectionId, RegionId, ServerId)
|
||||
@@ -70,7 +70,7 @@ upsert_by_connection(ConnectionId, VoiceState) ->
|
||||
-spec remove_connection(binary() | term()) -> ok.
|
||||
remove_connection(ConnectionId) ->
|
||||
ensure_tables(),
|
||||
case normalize_optional_binary(ConnectionId) of
|
||||
case guild_voice_connection_normalize:normalize_optional_binary(ConnectionId) of
|
||||
undefined ->
|
||||
ok;
|
||||
NormalizedConnectionId ->
|
||||
@@ -214,19 +214,6 @@ compare_count_rows({LeftId, LeftCount}, {RightId, RightCount}) ->
|
||||
false -> LeftCount > RightCount
|
||||
end.
|
||||
|
||||
-spec normalize_optional_binary(term()) -> binary() | undefined.
|
||||
normalize_optional_binary(undefined) ->
|
||||
undefined;
|
||||
normalize_optional_binary(null) ->
|
||||
undefined;
|
||||
normalize_optional_binary(Value) when is_binary(Value), byte_size(Value) > 0 -> Value;
|
||||
normalize_optional_binary(Value) when is_binary(Value) -> undefined;
|
||||
normalize_optional_binary(Value) when is_integer(Value) -> integer_to_binary(Value);
|
||||
normalize_optional_binary(Value) when is_list(Value) ->
|
||||
guild_voice_connection_normalize:normalize_optional_binary(Value);
|
||||
normalize_optional_binary(_) ->
|
||||
undefined.
|
||||
|
||||
-spec get_optional_field(map(), term(), term()) -> term().
|
||||
get_optional_field(Map, PrimaryKey, FallbackKey) ->
|
||||
get_optional_field(Map, PrimaryKey, FallbackKey, undefined).
|
||||
|
||||
@@ -159,7 +159,7 @@ maybe_put_live_voice_state(FallbackConnId, DefaultChanId, VoiceState, Acc) ->
|
||||
VoiceState,
|
||||
maps:get(connection_id, VoiceState, FallbackConnId)
|
||||
),
|
||||
ConnectionId = normalize_optional_binary(RawConnId),
|
||||
ConnectionId = guild_voice_connection_normalize:normalize_optional_binary(RawConnId),
|
||||
case ConnectionId of
|
||||
undefined ->
|
||||
Acc;
|
||||
@@ -175,7 +175,7 @@ maybe_put_default_channel_id(VoiceState, DefaultChannelId) ->
|
||||
VoiceState,
|
||||
maps:get(channel_id, VoiceState, undefined)
|
||||
),
|
||||
case normalize_optional_binary(ExistingId) of
|
||||
case guild_voice_connection_normalize:normalize_optional_binary(ExistingId) of
|
||||
undefined ->
|
||||
apply_default_channel_id(VoiceState, DefaultChannelId);
|
||||
ChannelId ->
|
||||
@@ -184,27 +184,11 @@ maybe_put_default_channel_id(VoiceState, DefaultChannelId) ->
|
||||
|
||||
-spec apply_default_channel_id(voice_state(), term()) -> voice_state().
|
||||
apply_default_channel_id(VoiceState, DefaultChannelId) ->
|
||||
case normalize_optional_binary(DefaultChannelId) of
|
||||
case guild_voice_connection_normalize:normalize_optional_binary(DefaultChannelId) of
|
||||
undefined -> VoiceState;
|
||||
ChannelId -> VoiceState#{<<"channel_id">> => ChannelId}
|
||||
end.
|
||||
|
||||
-spec normalize_optional_binary(term()) -> binary() | undefined.
|
||||
normalize_optional_binary(undefined) ->
|
||||
undefined;
|
||||
normalize_optional_binary(null) ->
|
||||
undefined;
|
||||
normalize_optional_binary(Value) when is_binary(Value), byte_size(Value) > 0 ->
|
||||
Value;
|
||||
normalize_optional_binary(Value) when is_binary(Value) ->
|
||||
undefined;
|
||||
normalize_optional_binary(Value) when is_integer(Value) ->
|
||||
integer_to_binary(Value);
|
||||
normalize_optional_binary(Value) when is_list(Value) ->
|
||||
guild_voice_connection_normalize:normalize_optional_binary(Value);
|
||||
normalize_optional_binary(_) ->
|
||||
undefined.
|
||||
|
||||
-ifdef(TEST).
|
||||
-include_lib("eunit/include/eunit.hrl").
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ diagnostic_info() ->
|
||||
init([]) ->
|
||||
process_flag(trap_exit, true),
|
||||
erlang:process_flag(fullsweep_after, 10),
|
||||
{ShardCount, _Source} = determine_shard_count(presence_bus_shards),
|
||||
{ShardCount, _Source} = shard_utils:determine_shard_count(presence_bus_shards),
|
||||
Shards = start_shards(ShardCount, #{}),
|
||||
{ok, #{shards => Shards, shard_count => ShardCount}, hibernate}.
|
||||
|
||||
@@ -127,22 +127,6 @@ code_change(_OldVsn, State, _Extra) ->
|
||||
erlang:garbage_collect(),
|
||||
{ok, State}.
|
||||
|
||||
-spec determine_shard_count(atom()) -> {pos_integer(), configured | auto}.
|
||||
determine_shard_count(ConfigKey) ->
|
||||
case fluxer_gateway_env:get(ConfigKey) of
|
||||
Value when is_integer(Value), Value > 0 ->
|
||||
{Value, configured};
|
||||
_ ->
|
||||
{default_shard_count(), auto}
|
||||
end.
|
||||
|
||||
-spec default_shard_count() -> pos_integer().
|
||||
default_shard_count() ->
|
||||
shard_utils:max_positive([
|
||||
erlang:system_info(logical_processors_available),
|
||||
erlang:system_info(schedulers_online)
|
||||
]).
|
||||
|
||||
-spec start_shards(pos_integer(), #{}) -> #{non_neg_integer() => shard()}.
|
||||
start_shards(Count, Acc) ->
|
||||
lists:foldl(fun start_shard_acc/2, Acc, lists:seq(0, Count - 1)).
|
||||
@@ -238,26 +222,12 @@ select_shard(Key, Count) when Count > 0 ->
|
||||
-spec find_shard_by_ref(reference(), #{non_neg_integer() => shard()}) ->
|
||||
{ok, non_neg_integer()} | not_found.
|
||||
find_shard_by_ref(Ref, Shards) ->
|
||||
maps:fold(
|
||||
fun
|
||||
(Index, #{ref := R}, _) when R =:= Ref -> {ok, Index};
|
||||
(_, _, Acc) -> Acc
|
||||
end,
|
||||
not_found,
|
||||
Shards
|
||||
).
|
||||
shard_utils:find_shard_by_ref(Ref, Shards).
|
||||
|
||||
-spec find_shard_by_pid(pid(), #{non_neg_integer() => shard()}) ->
|
||||
{ok, non_neg_integer()} | not_found.
|
||||
find_shard_by_pid(Pid, Shards) ->
|
||||
maps:fold(
|
||||
fun
|
||||
(Index, #{pid := P}, _) when P =:= Pid -> {ok, Index};
|
||||
(_, _, Acc) -> Acc
|
||||
end,
|
||||
not_found,
|
||||
Shards
|
||||
).
|
||||
shard_utils:find_shard_by_pid(Pid, Shards).
|
||||
|
||||
-spec safe_gen_server_call(pid() | atom(), term(), timeout()) -> term().
|
||||
safe_gen_server_call(Server, Request, Timeout) ->
|
||||
|
||||
@@ -193,7 +193,7 @@ add_user_to_owner_group(UserId, Acc) ->
|
||||
|
||||
-spec local_shard_count() -> pos_integer().
|
||||
local_shard_count() ->
|
||||
{Count, _Source} = determine_shard_count(presence_cache_shards),
|
||||
{Count, _Source} = presence_cache_shards:determine_count(presence_cache_shards),
|
||||
Count.
|
||||
|
||||
-spec select_shard(term(), pos_integer()) -> non_neg_integer().
|
||||
@@ -271,14 +271,6 @@ accumulate_ets_lookup(TableName, UserId, AccMap) ->
|
||||
error:badarg -> AccMap
|
||||
end.
|
||||
|
||||
-spec determine_shard_count(atom()) -> {pos_integer(), configured | auto}.
|
||||
determine_shard_count(ConfigKey) ->
|
||||
case clustered_ets_cache:determine_shard_count([ConfigKey]) of
|
||||
{Count, ConfigKey} -> {Count, configured};
|
||||
{Count, auto} -> {Count, auto};
|
||||
{Count, _Source} -> {Count, configured}
|
||||
end.
|
||||
|
||||
-spec normalize_shard_groups([{non_neg_integer(), [term()]}]) ->
|
||||
[{non_neg_integer(), [integer()]}].
|
||||
normalize_shard_groups(Groups) ->
|
||||
|
||||
@@ -66,7 +66,7 @@ handle_down_by_ref(Ref, State) ->
|
||||
-spec handle_down_by_pid(pid(), state()) -> state().
|
||||
handle_down_by_pid(Pid, State) ->
|
||||
Shards = maps:get(shards, State),
|
||||
case find_by_pid(Pid, Shards) of
|
||||
case shard_utils:find_shard_by_pid(Pid, Shards) of
|
||||
{ok, Index} -> restart_state(Index, State);
|
||||
not_found -> State
|
||||
end.
|
||||
@@ -196,14 +196,7 @@ memory_stats(State) ->
|
||||
-spec find_by_ref(reference(), #{non_neg_integer() => shard()}) ->
|
||||
{ok, non_neg_integer()} | not_found.
|
||||
find_by_ref(Ref, Shards) ->
|
||||
maps:fold(
|
||||
fun
|
||||
(Index, #{ref := R}, _) when R =:= Ref -> {ok, Index};
|
||||
(_, _, Acc) -> Acc
|
||||
end,
|
||||
not_found,
|
||||
Shards
|
||||
).
|
||||
shard_utils:find_shard_by_ref(Ref, Shards).
|
||||
|
||||
-spec start(non_neg_integer()) -> {ok, shard()} | {error, term()}.
|
||||
start(Index) ->
|
||||
@@ -306,18 +299,6 @@ merge_snapshot_reply(Snapshot, AccMap) when is_map(Snapshot) ->
|
||||
merge_snapshot_reply(_, AccMap) ->
|
||||
AccMap.
|
||||
|
||||
-spec find_by_pid(pid(), #{non_neg_integer() => shard()}) ->
|
||||
{ok, non_neg_integer()} | not_found.
|
||||
find_by_pid(Pid, Shards) ->
|
||||
maps:fold(
|
||||
fun
|
||||
(Index, #{pid := P}, _) when P =:= Pid -> {ok, Index};
|
||||
(_, _, Acc) -> Acc
|
||||
end,
|
||||
not_found,
|
||||
Shards
|
||||
).
|
||||
|
||||
-spec error_reply(term()) -> term().
|
||||
error_reply({put, _, _}) -> {error, unavailable};
|
||||
error_reply({delete, _}) -> {error, unavailable};
|
||||
|
||||
@@ -36,10 +36,7 @@
|
||||
|
||||
-spec determine_count() -> {pos_integer(), configured | auto}.
|
||||
determine_count() ->
|
||||
case fluxer_gateway_env:get(presence_shards) of
|
||||
Value when is_integer(Value), Value > 0 -> {Value, configured};
|
||||
_ -> {default_count(), auto}
|
||||
end.
|
||||
shard_utils:determine_shard_count(presence_shards).
|
||||
|
||||
-spec start(non_neg_integer()) -> {ok, shard()} | {error, term()}.
|
||||
start(Index) ->
|
||||
@@ -157,33 +154,16 @@ pid_from_table(Key) ->
|
||||
-spec find_by_ref(reference(), #{non_neg_integer() => shard()}) ->
|
||||
{ok, non_neg_integer()} | not_found.
|
||||
find_by_ref(Ref, Shards) ->
|
||||
maps:fold(
|
||||
fun
|
||||
(Index, #{ref := R}, _) when R =:= Ref -> {ok, Index};
|
||||
(_, _, Acc) -> Acc
|
||||
end,
|
||||
not_found,
|
||||
Shards
|
||||
).
|
||||
shard_utils:find_shard_by_ref(Ref, Shards).
|
||||
|
||||
-spec find_by_pid(pid(), #{non_neg_integer() => shard()}) ->
|
||||
{ok, non_neg_integer()} | not_found.
|
||||
find_by_pid(Pid, Shards) ->
|
||||
maps:fold(
|
||||
fun
|
||||
(Index, #{pid := P}, _) when P =:= Pid -> {ok, Index};
|
||||
(_, _, Acc) -> Acc
|
||||
end,
|
||||
not_found,
|
||||
Shards
|
||||
).
|
||||
shard_utils:find_shard_by_pid(Pid, Shards).
|
||||
|
||||
-spec default_count() -> pos_integer().
|
||||
default_count() ->
|
||||
shard_utils:max_positive([
|
||||
erlang:system_info(logical_processors_available),
|
||||
erlang:system_info(schedulers_online)
|
||||
]).
|
||||
clustered_ets_cache:default_shard_count().
|
||||
|
||||
-spec ensure_shard(user_id(), state()) -> {non_neg_integer(), state()}.
|
||||
ensure_shard(Key, State) ->
|
||||
|
||||
@@ -269,7 +269,7 @@ push_eligible(State) ->
|
||||
-spec build_push_create_params(user_id(), map()) -> map() | undefined.
|
||||
build_push_create_params(UserId, Data) ->
|
||||
AuthorIdBin = maps:get(<<"id">>, maps:get(<<"author">>, Data, #{}), undefined),
|
||||
case parse_snowflake(<<"author_id">>, AuthorIdBin) of
|
||||
case guild_dispatch_decorate:parse_snowflake(<<"author_id">>, AuthorIdBin) of
|
||||
undefined ->
|
||||
undefined;
|
||||
AuthorId ->
|
||||
@@ -439,14 +439,7 @@ session_holds_push(Session) ->
|
||||
|
||||
-spec extract_snowflake(binary(), map()) -> integer() | undefined.
|
||||
extract_snowflake(FieldName, Data) ->
|
||||
parse_snowflake(FieldName, maps:get(FieldName, Data, undefined)).
|
||||
|
||||
-spec parse_snowflake(binary(), term()) -> integer() | undefined.
|
||||
parse_snowflake(FieldName, Value) ->
|
||||
case validation:validate_snowflake(FieldName, Value) of
|
||||
{ok, Id} -> Id;
|
||||
{error, _, _} -> undefined
|
||||
end.
|
||||
guild_dispatch_decorate:parse_snowflake(FieldName, maps:get(FieldName, Data, undefined)).
|
||||
|
||||
-ifdef(TEST).
|
||||
-include_lib("eunit/include/eunit.hrl").
|
||||
|
||||
@@ -96,7 +96,7 @@ init([]) ->
|
||||
erlang:process_flag(fullsweep_after, 0),
|
||||
_ = fluxer_gateway_env:load(),
|
||||
session_manager_shards:ensure_shard_table(),
|
||||
{ShardCount, _Source} = determine_shard_count(),
|
||||
{ShardCount, _Source} = shard_utils:determine_shard_count(session_shards),
|
||||
Shards = session_manager_shards:start_shards(ShardCount),
|
||||
State = #{shards => Shards, shard_count => ShardCount},
|
||||
session_manager_shards:sync_shard_table(State),
|
||||
@@ -316,19 +316,3 @@ atom_list([Value | Rest], Acc) when is_atom(Value) ->
|
||||
atom_list(Rest, [Value | Acc]);
|
||||
atom_list(_, _) ->
|
||||
error.
|
||||
|
||||
-spec determine_shard_count() -> {pos_integer(), configured | auto}.
|
||||
determine_shard_count() ->
|
||||
case fluxer_gateway_env:get(session_shards) of
|
||||
Value when is_integer(Value), Value > 0 ->
|
||||
{Value, configured};
|
||||
_ ->
|
||||
{default_shard_count(), auto}
|
||||
end.
|
||||
|
||||
-spec default_shard_count() -> pos_integer().
|
||||
default_shard_count() ->
|
||||
shard_utils:max_positive([
|
||||
erlang:system_info(logical_processors_available),
|
||||
erlang:system_info(schedulers_online)
|
||||
]).
|
||||
@@ -93,28 +93,12 @@ safe_shard_call(Pid, Request) ->
|
||||
-spec find_shard_by_ref(reference(), #{non_neg_integer() => shard()}) ->
|
||||
{ok, non_neg_integer()} | not_found.
|
||||
find_shard_by_ref(Ref, Shards) ->
|
||||
maps:fold(
|
||||
fun
|
||||
(_Index, _Shard, {ok, _} = Found) -> Found;
|
||||
(Index, #{ref := ExistingRef}, not_found) when ExistingRef =:= Ref -> {ok, Index};
|
||||
(_Index, _Shard, not_found) -> not_found
|
||||
end,
|
||||
not_found,
|
||||
Shards
|
||||
).
|
||||
shard_utils:find_shard_by_ref(Ref, Shards).
|
||||
|
||||
-spec find_shard_by_pid(pid(), #{non_neg_integer() => shard()}) ->
|
||||
{ok, non_neg_integer()} | not_found.
|
||||
find_shard_by_pid(Pid, Shards) ->
|
||||
maps:fold(
|
||||
fun
|
||||
(_Index, _Shard, {ok, _} = Found) -> Found;
|
||||
(Index, #{pid := ExistingPid}, not_found) when ExistingPid =:= Pid -> {ok, Index};
|
||||
(_Index, _Shard, not_found) -> not_found
|
||||
end,
|
||||
not_found,
|
||||
Shards
|
||||
).
|
||||
shard_utils:find_shard_by_pid(Pid, Shards).
|
||||
|
||||
-ifdef(TEST).
|
||||
-include_lib("eunit/include/eunit.hrl").
|
||||
@@ -188,6 +172,21 @@ aggregate_handoff_to_topology_marks_invalid_reply_as_failed_test() ->
|
||||
aggregate_handoff_to_topology(['peer@host'], State),
|
||||
InvalidShardPid ! stop.
|
||||
|
||||
aggregate_handoff_to_topology_counts_unavailable_and_bare_replies_test() ->
|
||||
ExitedShardPid = spawn(fun() -> ok end),
|
||||
ok = gateway_retry_timer:wait(5),
|
||||
BareShardPid = spawn(fun() -> shard_bare_reply_test_loop(2) end),
|
||||
State = #{
|
||||
shards => #{
|
||||
0 => #{pid => ExitedShardPid, ref => make_ref()},
|
||||
1 => #{pid => BareShardPid, ref => make_ref()}
|
||||
},
|
||||
shard_count => 2
|
||||
},
|
||||
{#{attempted := 3, handed_off := 2}, _State} =
|
||||
aggregate_handoff_to_topology(['peer@host'], State),
|
||||
BareShardPid ! stop.
|
||||
|
||||
shard_reconnect_test_loop(DrainCount) ->
|
||||
receive
|
||||
{'$gen_call', From, reconnect_drain} ->
|
||||
@@ -217,10 +216,13 @@ shard_handoff_test_loop(Result) ->
|
||||
end.
|
||||
|
||||
shard_invalid_reply_test_loop() ->
|
||||
shard_bare_reply_test_loop(invalid_reply).
|
||||
|
||||
shard_bare_reply_test_loop(Reply) ->
|
||||
receive
|
||||
{'$gen_call', From, _Request} ->
|
||||
gen_server:reply(From, invalid_reply),
|
||||
shard_invalid_reply_test_loop();
|
||||
gen_server:reply(From, Reply),
|
||||
shard_bare_reply_test_loop(Reply);
|
||||
stop ->
|
||||
ok
|
||||
after 5000 ->
|
||||
|
||||
@@ -5,6 +5,9 @@
|
||||
|
||||
-export([
|
||||
max_positive/1,
|
||||
determine_shard_count/1,
|
||||
find_shard_by_ref/2,
|
||||
find_shard_by_pid/2,
|
||||
safe_gen_call/3,
|
||||
safe_gen_call_detailed/3,
|
||||
safe_gen_call_remote/3,
|
||||
@@ -14,10 +17,47 @@
|
||||
check_mailbox_pressure/1
|
||||
]).
|
||||
|
||||
-export_type([shard/0]).
|
||||
|
||||
-type shard() :: #{pid := pid(), ref := reference()}.
|
||||
|
||||
-spec max_positive(list()) -> pos_integer().
|
||||
max_positive(Candidates) ->
|
||||
lists:max([C || C <- Candidates, is_integer(C), C > 0] ++ [1]).
|
||||
|
||||
-spec determine_shard_count(atom()) -> {pos_integer(), configured | auto}.
|
||||
determine_shard_count(ConfigKey) ->
|
||||
case fluxer_gateway_env:get(ConfigKey) of
|
||||
Value when is_integer(Value), Value > 0 ->
|
||||
{Value, configured};
|
||||
_ ->
|
||||
{clustered_ets_cache:default_shard_count(), auto}
|
||||
end.
|
||||
|
||||
-spec find_shard_by_ref(reference(), #{non_neg_integer() => shard()}) ->
|
||||
{ok, non_neg_integer()} | not_found.
|
||||
find_shard_by_ref(Ref, Shards) ->
|
||||
maps:fold(
|
||||
fun
|
||||
(Index, #{ref := R}, _) when R =:= Ref -> {ok, Index};
|
||||
(_, _, Acc) -> Acc
|
||||
end,
|
||||
not_found,
|
||||
Shards
|
||||
).
|
||||
|
||||
-spec find_shard_by_pid(pid(), #{non_neg_integer() => shard()}) ->
|
||||
{ok, non_neg_integer()} | not_found.
|
||||
find_shard_by_pid(Pid, Shards) ->
|
||||
maps:fold(
|
||||
fun
|
||||
(Index, #{pid := P}, _) when P =:= Pid -> {ok, Index};
|
||||
(_, _, Acc) -> Acc
|
||||
end,
|
||||
not_found,
|
||||
Shards
|
||||
).
|
||||
|
||||
-spec safe_gen_call(pid() | atom(), term(), pos_integer()) -> term().
|
||||
safe_gen_call(Pid, Request, Timeout) ->
|
||||
try
|
||||
|
||||
Reference in new issue
Block a user