Github user rnewson commented on a diff in the pull request:

    https://github.com/apache/couchdb-couch-epi/pull/12#discussion_r40776106
  
    --- Diff: src/couch_epi_sup.erl ---
    @@ -32,13 +47,216 @@
     start_link() ->
         supervisor:start_link({local, ?MODULE}, ?MODULE, []).
     
    +plugin_childspecs(Plugin, Children) ->
    +    Plugins = application:get_env(couch_epi, plugins, []),
    +    plugin_childspecs(Plugin, Plugins, Children).
    +
     %% ===================================================================
     %% Supervisor callbacks
     %% ===================================================================
     
     init([]) ->
    -    Children = [
    -        ?CHILD(couch_epi_server, worker),
    -        ?SUP(couch_epi_keeper_sup, [])
    +    {ok, { {one_for_one, 5, 10}, keepers()} }.
    +
    +%% ------------------------------------------------------------------
    +%% Internal Function Definitions
    +%% ------------------------------------------------------------------
    +
    +keepers() ->
    +    Plugins = application:get_env(couch_epi, plugins, []),
    +    Definitions0 = couch_epi_plugin:grouped_definitions(Plugins),
    +    Definitions1 = reorder(Definitions0),
    +    Children = keeper_childspecs(Definitions1),
    +    remove_duplicates(Children).
    +
    +plugin_childspecs(Plugin, Plugins, Children) ->
    +    Definitions = couch_epi_plugin:grouped_definitions([Plugin]),
    +    ExtraChildren = couch_epi_plugin:plugin_processes(Plugin, Plugins),
    +    merge(ExtraChildren, Children) ++ childspecs(Definitions).
    +
    +childspecs(Definitions) ->
    +    lists:map(fun({{Kind, Key}, Defs}) ->
    +        CodeGen = couch_epi_plugin:codegen(Kind),
    +        Handle = CodeGen:get_handle(Key),
    +        Modules = lists:append([modules(Spec) || {_App, Spec} <- Defs]),
    +        Name = service_name(Key) ++ "|" ++ atom_to_list(Kind),
    +        code_monitor(Name, [Handle], [Handle|Modules])
    +    end, Definitions).
    +
    +%% ------------------------------------------------------------------
    +%% Helper Function Definitions
    +%% ------------------------------------------------------------------
    +
    +reorder(Definitions) ->
    +    lists:sort(fun(A, B) ->
    +       kinds_order(A) =< kinds_order(B)
    +    end, Definitions).
    +
    +kinds_order({{providers, _Key}, _Specs}) -> 3;
    +kinds_order({{services, _Key}, _Specs}) -> 1;
    +kinds_order({{data_providers, _Key}, _Specs}) -> 4;
    +kinds_order({{data_subscriptions, _Key}, _Specs}) -> 2.
    +
    +remove_duplicates(Definitions) ->
    +    remove_duplicates(Definitions, []).
    +
    +remove_duplicates([Spec | Rest], Acc) ->
    +    case has_duplicate(Acc, Spec) of
    +        true ->
    +            remove_duplicates(Rest, Acc);
    +        false ->
    +            remove_duplicates(Rest, [Spec | Acc])
    +    end;
    +remove_duplicates([], Acc) ->
    +    Acc.
    +
    +
    +has_duplicate(Acc, {IdA, _, _, _, _, _}) ->
    +    lists:any(fun({IdB, _, _, _, _, _}) ->
    +        IdA == IdB
    +    end, Acc).
    +
    +keeper_childspecs(Definitions) ->
    +    lists:map(fun({{Kind, Key}, _Specs}) ->
    +        Name = service_name(Key) ++ "|keeper",
    +        CodeGen = couch_epi_plugin:codegen(Kind),
    +        Handle = CodeGen:get_handle(Key),
    +        keeper(Name, [provider_kind(Kind), Key, CodeGen], [Handle])
    +    end, Definitions).
    +
    +keeper(Name, Args, Modules) ->
    +    {"couch_epi|" ++ Name, {couch_epi_module_keeper, start_link,
    +        Args}, permanent, 5000, worker, Modules}.
    +
    +code_monitor(Name, Args, Modules0) ->
    +    Modules = [couch_epi_codechange_monitor | Modules0],
    +    {"couch_epi_codechange_monitor|" ++ Name,
    +        {couch_epi_codechange_monitor, start_link, Args}, permanent, 5000, 
worker, Modules}.
    +
    +provider_kind(services) -> providers;
    +provider_kind(data_subscriptions) -> data_providers;
    +provider_kind(Kind) -> Kind.
    +
    +service_name({ServiceId, Key}) ->
    +    atom_to_list(ServiceId) ++ ":" ++ atom_to_list(Key);
    +service_name(ServiceId) ->
    +    atom_to_list(ServiceId).
    +
    +modules(#couch_epi_spec{kind = providers, value = Module}) ->
    +    [Module];
    +modules(#couch_epi_spec{kind = services, value = Module}) ->
    +    [Module];
    +modules(#couch_epi_spec{kind = data_providers, value = Value}) ->
    +    case Value of
    +        {module, Module} -> [Module];
    +        _ -> []
    +    end;
    +modules(#couch_epi_spec{kind = data_subscriptions, behaviour = Module}) ->
    +    [Module].
    +
    +merge([], Children) ->
    +    Children;
    +merge([{Id, _, _, _, _, _} = Spec | Rest], Children) ->
    +    merge(Rest, lists:keystore(Id, 1, Children, Spec)).
    --- End diff --
    
    why not http://www.erlang.org/doc/man/lists.html#ukeymerge-3?


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at [email protected] or file a JIRA ticket
with INFRA.
---

Reply via email to