Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cabol.280.fixes and improvements on sumo events #281

Merged
merged 3 commits into from
Oct 11, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion rebar.config
Original file line number Diff line number Diff line change
Expand Up @@ -106,4 +106,8 @@
{base_plt_prefix, "sumo_db"}
]}.

{plugins, [rebar3_hex]}.
{plugins, [rebar3_hex]}.

%% == Shell ==

{shell, [{apps, [sumo_db]}]}.
5 changes: 2 additions & 3 deletions src/adapter_test_helpers/sumo_basic_test_helper.erl
Original file line number Diff line number Diff line change
Expand Up @@ -229,9 +229,8 @@ init_store(Name) ->
%%% Internal functions
%%%=============================================================================

pick_up_event({Name, _, _} = Event) ->
EventManager = sumo_config:get_event_manager(Name),
EventManager:pick_up_event(Event).
pick_up_event(Event) ->
sumo_test_people_events_manager:pick_up_event(Event).

create(Name, Args) ->
Res = sumo:persist(Name, Args),
Expand Down
12 changes: 6 additions & 6 deletions src/adapter_test_helpers/sumo_events_test_helper.erl
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@
-spec events_manager_supervisor_running(Config :: config()) -> ok.
events_manager_supervisor_running(Config) ->
{_, DocName} = lists:keyfind(name, 1, Config),

case sumo_config:get_event_manager(DocName) of
undefined ->
case sumo_config:get_event_managers(DocName) of
[] ->
ok;
EventManager ->
ct:comment("~p should be running", [EventManager]),
[EventManager] = gen_event:which_handlers(EventManager),
EventManagers ->
ct:comment("~p should be running", [EventManagers]),
EventManagers =
[hd(gen_event:which_handlers(EM)) || EM <- EventManagers],
ok
end.
4 changes: 1 addition & 3 deletions src/adapter_test_helpers/sumo_test_people_events_manager.erl
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,7 @@

-spec pick_up_event(tuple()) -> ok | no_event.
pick_up_event(Event) ->
EventMgr = proplists:get_value(
people, application:get_env(sumo_db, events, [])),
gen_event:call(EventMgr, ?MODULE, {pick_up_event, Event}).
gen_event:call(?MODULE, ?MODULE, {pick_up_event, Event}).

-spec init([]) -> {ok, state()}.
init([]) ->
Expand Down
134 changes: 109 additions & 25 deletions src/sumo_config.erl
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,16 @@
get_store/1,
get_props/1,
get_prop_value/2,
get_prop_value/3,
get_events/0,
get_event_manager/1
get_event_managers/0,
get_event_managers/1,
add_event_managers/2,
remove_event_managers/2
]).

-include_lib("stdlib/include/ms_transform.hrl").

%%%===================================================================
%%% Types
%%%===================================================================
Expand All @@ -51,28 +57,18 @@

-spec init() -> ok.
init() ->
sumo_config = ets:new(sumo_config, [
protected,
named_table,
{read_concurrency, true}
]),
Docs = application:get_env(sumo_db, docs, []),
Events = application:get_env(sumo_db, events, []),
NewDocs = lists:foldl(fun({DocName, EventManager}, Acc) ->
case lists:keyfind(DocName, 1, Acc) of
{DocName, Store, Props} ->
NewDoc = {DocName, Store, Props#{event_manager => EventManager}},
lists:keyreplace(DocName, 1, Acc, NewDoc);
_ ->
Acc
end
end, Docs, Events),
true = ets:insert(sumo_config, NewDocs),
ok.
case ets:info(?MODULE) of
undefined ->
do_init();
_ ->
true = ets:delete(?MODULE),
do_init()
end.

-spec get_docs() -> [doc_config()].
get_docs() ->
application:get_env(sumo_db, docs, []).
MS = ets:fun2ms(fun({X, Y, Z}) -> {X, Y, Z} end),
ets:select(?MODULE, MS).

-spec get_doc(atom()) -> doc_config() | undefined.
get_doc(DocName) ->
Expand All @@ -91,23 +87,111 @@ get_props(DocName) ->

-spec get_prop_value(atom(), atom()) -> term().
get_prop_value(DocName, Prop) ->
maps:get(Prop, get_props(DocName), undefined).
get_prop_value(DocName, Prop, undefined).

-spec get_prop_value(atom(), atom(), term()) -> term().
get_prop_value(DocName, Prop, Default) ->
maps:get(Prop, get_props(DocName), Default).

-spec get_events() -> [event_config()].
get_events() ->
application:get_env(sumo_db, events, []).

-spec get_event_manager(atom()) -> module().
get_event_manager(DocName) ->
get_prop_value(DocName, event_manager).
-spec get_event_managers() -> [module()].
get_event_managers() ->
lookup_element('$event_managers', 2, []).

-spec get_event_managers(atom()) -> [module()].
get_event_managers(DocName) ->
get_prop_value(DocName, event_managers, []).

-spec add_event_managers(atom(), [module()] | module()) -> [module()].
add_event_managers(DocName, EventManagers) ->
load_entries([get_doc(DocName)], [{DocName, EventManagers}]),
get_event_managers(DocName).

-spec remove_event_managers(atom(), [module()] | module()) -> [module()].
remove_event_managers(DocName, EventManagers) when is_list(EventManagers) ->
Docs = [get_doc(DocName)],
load_entries(Docs, [{DocName, EventManagers}], fun lists:subtract/2),
get_event_managers(DocName);
remove_event_managers(DocName, EventManagers) when is_atom(EventManagers) ->
remove_event_managers(DocName, [EventManagers]).

%%%===================================================================
%%% Internal functions
%%%===================================================================

%% @private
do_init() ->
?MODULE = ets:new(?MODULE, [named_table, public, {read_concurrency, true}]),
Docs = application:get_env(sumo_db, docs, []),
Events = application:get_env(sumo_db, events, []),
UpdatedDocs = load_events(Docs, Events),
EvManagers = load_event_managers(UpdatedDocs),
Entries = [{'$event_managers', EvManagers} | UpdatedDocs],
set_entries(Entries).

%% @private
set_entries(Entries) ->
true = ets:insert(?MODULE, Entries),
ok.

%% @private
load_entries(Docs, Events) ->
load_entries(Docs, Events, fun lists:append/2).

%% @private
load_entries(Docs, Events, Fun) ->
UpdatedDocs = load_events(Docs, Events, Fun),
ok = set_entries(UpdatedDocs),
EvManagers = load_event_managers(get_docs()),
set_entries({'$event_managers', EvManagers}).

%% @private
load_events(Docs, Events) ->
load_events(Docs, Events, fun lists:append/2).

%% @private
load_events(Docs, Events, Fun) ->
lists:foldl(fun({DocName, EventManagers}, DocAcc) ->
update_doc_entry(DocName, EventManagers, Fun, DocAcc)
end, Docs, Events).

%% @private
load_event_managers(Docs) ->
lists:usort(lists:foldl(fun({_, _, Props}, Acc) ->
maps:get(event_managers, Props, []) ++ Acc
end, [], Docs)).

%% @private
update_doc_entry(_DocName, [], _Fun, Docs) ->
Docs;
update_doc_entry('_', EvManagers, Fun, Docs) when is_list(EvManagers) ->
DocNames = [DocName || {DocName, _, _} <- Docs],
lists:foldl(fun(DocName, DocAcc) ->
update_doc_entry(DocName, EvManagers, Fun, DocAcc)
end, Docs, DocNames);
update_doc_entry(DocName, EvManagers, Fun, Docs) when is_list(EvManagers) ->
case lists:keyfind(DocName, 1, Docs) of
{DocName, Store, Props} ->
CurrentEvManagers = maps:get(event_managers, Props, []),
NewEventManagers = lists:usort(Fun(CurrentEvManagers, EvManagers)),
NewDoc = {DocName, Store, Props#{event_managers => NewEventManagers}},
lists:keyreplace(DocName, 1, Docs, NewDoc);
_ ->
Docs
end;
update_doc_entry(DocName, EvManagers, Fun, Docs) when is_atom(EvManagers) ->
update_doc_entry(DocName, [EvManagers], Fun, Docs).

%% @private
lookup_element(Key, Pos) ->
lookup_element(Key, Pos, undefined).

%% @private
lookup_element(Key, Pos, Default) ->
try ets:lookup_element(?MODULE, Key, Pos)
catch
_:_ -> undefined
_:_ -> Default
end.
10 changes: 7 additions & 3 deletions src/sumo_event.erl
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,11 @@ dispatch(DocName, Event) ->
%% @doc Dispatch an event through gen_event:notify/2.
-spec dispatch(sumo:schema_name(), term(), term()) -> ok.
dispatch(DocName, Event, Args) ->
case sumo_config:get_event_manager(DocName) of
undefined -> ok;
EventManager -> gen_event:notify(EventManager, {DocName, Event, Args})
case sumo_config:get_event_managers(DocName) of
[] ->
ok;
EventManagers ->
lists:foreach(fun(EventManager) ->
gen_event:notify(EventManager, {DocName, Event, Args})
end, EventManagers)
end.
5 changes: 2 additions & 3 deletions src/sumo_event_manager_sup.erl
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,8 @@ start_link() -> supervisor:start_link({local, ?MODULE}, ?MODULE, []).

-spec init(any()) -> {ok, {supervisor:sup_flags(), [supervisor:child_spec()]}}.
init([]) ->
Events = sumo_config:get_events(),
EventsManagers = lists:usort([Manager || {_, Manager} <- Events]),
ManagersList = [manager(EventManager) || EventManager <- EventsManagers],
EventManagers = sumo_config:get_event_managers(),
ManagersList = [manager(EventManager) || EventManager <- EventManagers],
{ok, {{one_for_one, 5, 10}, ManagersList}}.

%%%=============================================================================
Expand Down
1 change: 1 addition & 0 deletions test/conditional_logic_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,5 @@ init_per_suite(Config) ->

-spec end_per_suite(config()) -> config().
end_per_suite(Config) ->
_ = application:stop(sumo_db),
Config.
4 changes: 1 addition & 3 deletions test/sumo_basic_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,6 @@ all() ->
-spec init_per_suite(config()) -> config().
init_per_suite(Config) ->
ok = sumo_test_utils:start_apps(),
EventMgr = proplists:get_value(
people, application:get_env(sumo_db, events, [])),
gen_event:add_handler(EventMgr, sumo_test_people_events_manager, []),
[{name, people} | Config].

-spec init_per_testcase(atom(), config()) -> config().
Expand All @@ -57,4 +54,5 @@ init_per_testcase(_, Config) ->

-spec end_per_suite(config()) -> config().
end_per_suite(Config) ->
_ = application:stop(sumo_db),
Config.
Loading