Skip to content

Commit

Permalink
Rework how shaper_srv are started and found entirely
Browse files Browse the repository at this point in the history
  • Loading branch information
NelsonVides committed Apr 27, 2022
1 parent 535617a commit 8433f2b
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 129 deletions.
71 changes: 0 additions & 71 deletions src/ejabberd_shaper_sup.erl

This file was deleted.

6 changes: 3 additions & 3 deletions src/ejabberd_sup.erl
Original file line number Diff line number Diff line change
Expand Up @@ -146,9 +146,9 @@ init([]) ->
worker,
[mod_muc_iq]},
ShaperSup =
{ejabberd_shaper_sup,
{ejabberd_shaper_sup, start_link, []},
permanent, infinity, supervisor, [ejabberd_shaper_sup]},
{mongoose_shaper_sup,
{mongoose_shaper_sup, start_link, []},
permanent, infinity, supervisor, [mongoose_shaper_sup]},
PG =
{pg,
{pg, start_link, [mim_scope]},
Expand Down
58 changes: 58 additions & 0 deletions src/mongoose_shaper_sup.erl
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
-module(mongoose_shaper_sup).

-behaviour(supervisor).

%% API
-export([start_link/0, get_workers/0, select_worker/1]).
-ignore_xref([start_link/0]).

%% Supervisor callbacks
-export([init/1]).

-spec start_link() -> {ok, pid()} | ignore | {error, term()}.
start_link() ->
supervisor:start_link({local, ?MODULE}, ?MODULE, []).

-spec init([]) -> {ok, {#{strategy => one_for_one, intensity => 100, period => 5},
[supervisor:child_spec()]}}.
init([]) ->
SupFlags = #{strategy => one_for_one, intensity => 100, period => 5},
WorkerNames = worker_names(),
TupleNames = list_to_tuple(WorkerNames),
persistent_term:put(?MODULE, TupleNames),
Shapers = [child_spec(Name) || Name <- WorkerNames],
{ok, { SupFlags, Shapers }}.

-spec child_spec(atom()) -> supervisor:child_spec().
child_spec(ProcName) ->
#{id => ProcName,
start => {shaper_srv, start_link, [ProcName]},
restart => permanent,
shutdown => 5000,
type => worker,
modules => [shaper_srv]}.

-spec get_workers() -> [atom()].
get_workers() ->
tuple_to_list(persistent_term:get(?MODULE)).

-spec select_worker(term()) -> atom().
select_worker(Key) ->
N = 1 + erlang:phash2(Key, worker_count()),
Workers = persistent_term:get(?MODULE),
element(N, Workers).

-spec worker_names() -> [atom()].
worker_names() ->
[build_worker_name(N) || N <- lists:seq(1, worker_count())].

-spec build_worker_name(integer()) -> atom().
build_worker_name(N) ->
list_to_atom(worker_prefix() ++ integer_to_list(N)).

-spec worker_prefix() -> string().
worker_prefix() ->
"mongoose_shaper_".

worker_count() ->
10.
61 changes: 6 additions & 55 deletions src/shaper_srv.erl
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,8 @@
-behaviour(gen_server).

%% API Function Exports
-export([start_link/1,
worker_names/0,
child_specs/1,
wait/5,
reset_shapers/1,
reset_all_shapers/1]).

-ignore_xref([reset_all_shapers/1, reset_shapers/1, start_link/1]).
-export([start_link/1, wait/5, reset_all_shapers/1]).
-ignore_xref([start_link/1, reset_all_shapers/1]).

%% Record definitions
-record(state, {
Expand All @@ -32,66 +26,23 @@
-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).

%% API Function Definitions
%% ------------------------------------------------------------------

-spec worker_names() -> [{non_neg_integer(), atom()}].
worker_names() ->
[{N, build_worker_name(N)} || N <- lists:seq(0, worker_count() - 1)].

-spec child_specs([{non_neg_integer(), atom()}]) -> [supervisor:child_spec()].
child_specs(WorkerNames) ->
[child_spec(ProcName) || {_N, ProcName} <- WorkerNames].

-spec build_worker_name(integer()) -> atom().
build_worker_name(N) ->
list_to_atom(worker_prefix() ++ integer_to_list(N)).

-spec worker_prefix() -> string().
worker_prefix() ->
"ejabberd_shaper_".

worker_count() ->
10.

-spec child_spec(atom()) -> supervisor:child_spec().
child_spec(ProcName) ->
{ProcName,
{?MODULE, start_link, [ProcName]},
permanent,
5000,
worker,
[?MODULE]}.

-spec start_link(atom()) -> ignore | {error, _} | {ok, pid()}.
start_link(ProcName) ->
gen_server:start_link({local, ProcName}, ?MODULE, [], []).

-spec worker_name(non_neg_integer()) -> atom().
worker_name(N) ->
ets:lookup_element(ejabberd_shaper_sup, N, 2).

-spec worker_number(term()) -> non_neg_integer().
worker_number(Tag) ->
erlang:phash2(Tag, worker_count()).

-spec select_worker(term()) -> atom().
select_worker(Tag) ->
N = worker_number(Tag),
worker_name(N).

%% @doc Shapes the caller from executing the action.
-spec wait(HostType :: mongooseim:host_type(),
Domain :: jid:server(),
Action :: atom(),
FromJID :: jid:jid() | global,
Size :: integer()) -> ok | {error, max_delay_reached}.
wait(HostType, Domain, Action, FromJID, Size) ->
gen_server:call(select_worker(FromJID),
{wait, HostType, Domain, Action, FromJID, Size}).
Worker = mongoose_shaper_sup:select_worker(FromJID),
gen_server:call(Worker, {wait, HostType, Domain, Action, FromJID, Size}).

%% @doc Ask all shaper servers to forget current shapers and read settings again
reset_all_shapers(_HostType) ->
[reset_shapers(ProcName) || {_N, ProcName} <- ets:tab2list(ejabberd_shaper_sup)].
[reset_shapers(ProcName) || ProcName <- mongoose_shaper_sup:get_workers()].

%% @doc Ask server to forget its shapers
reset_shapers(ProcName) ->
Expand Down Expand Up @@ -180,7 +131,7 @@ delete_old_shapers(State = #state{shapers = Shapers, a_times = Times, ttl = TTL}
end, init_dicts(State), Times).

-spec create_shaper(mongooseim:host_type(), key()) ->
none | {maxrate, _, 0, non_neg_integer()}.
none | shaper:shaper().
create_shaper(HostType, Key) ->
shaper:new(request_shaper_name(HostType, Key)).

Expand Down

0 comments on commit 8433f2b

Please sign in to comment.