Packages

An etcd client built on top of gun and egrpc.

Current section

Files

Jump to
etcdgun src etcdgun_watcher_sup.erl
Raw

src/etcdgun_watcher_sup.erl

-module(etcdgun_watcher_sup).
-behaviour(supervisor).
-export([start_link/0, init/1]).
-export([start_child/5, stop_child/2]).
-define(WATCHER_EVENT_MANAGER, etcdgun_event_manager_table).
-record(watcher_event_manager, {id , event_manager_pid}).
start_link() ->
etcdgun_watcher:create_watch_cache_table(),
supervisor:start_link({local, ?MODULE}, ?MODULE, []).
start_child(Client, WatcherName, EventHandler, EventHandlerArgs, Requests) ->
{ok, EventMgr} = etcdgun_event_manager_sup:start_event_manager(),
try
case gen_event:add_handler(EventMgr, EventHandler, EventHandlerArgs) of
ok ->
Args = [Client, WatcherName, EventMgr, Requests],
Child = #{
id => {Client, WatcherName},
start => {etcdgun_watcher, start_link, Args},
restart => transient,
shutdown => 1000,
type => worker,
modules => [etcdgun_watcher]
},
case supervisor:start_child(?MODULE, Child) of
{ok, Pid} when is_pid(Pid) ->
Record = #watcher_event_manager{
id = {Client, WatcherName},
event_manager_pid = EventMgr
},
ets:insert(?WATCHER_EVENT_MANAGER, Record),
{ok, Pid};
{error, Reason} -> error(Reason)
end;
{'EXIT', Reason} ->
error(Reason);
Other ->
error(Other)
end
catch
error:Reason1 ->
gen_event:stop(EventMgr),
{error, Reason1}
end.
-spec stop_child(atom(), atom()) -> ok | {error, not_found}.
stop_child(Client, WatcherName) ->
case supervisor:terminate_child(?MODULE, {Client, WatcherName}) of
ok ->
ok = supervisor:delete_child(?MODULE, {Client, WatcherName}),
case ets:lookup(?WATCHER_EVENT_MANAGER, {Client, WatcherName}) of
[#watcher_event_manager{event_manager_pid = EventMgr} = Record] ->
ets:delete_object(?WATCHER_EVENT_MANAGER, Record),
ok = etcdgun_event_manager_sup:stop_event_manager(EventMgr),
ok;
[] -> ok
end,
ok;
{error, not_found} = E -> E
end.
init([]) ->
case ets:info(?WATCHER_EVENT_MANAGER) of
undefined ->
ets:new(?WATCHER_EVENT_MANAGER,
[named_table, public, set, {keypos, #watcher_event_manager.id}]);
_ -> ok
end,
MaxRestarts = 300,
MaxSecondsBetweenRestarts = 10,
SupFlags = #{
strategy => one_for_one,
intensity => MaxRestarts,
period => MaxSecondsBetweenRestarts
},
{ok, {SupFlags, []}}.