diff --git a/src/config.erl b/src/config.erl index 50d2a5d..f109067 100644 --- a/src/config.erl +++ b/src/config.erl @@ -300,17 +300,29 @@ handle_call(reload, _From, Config) -> end, dict:new(), Config#config.ini_files), % Update ets with anything we just read % from disk - dict:fold(fun(K, V, _) -> - ets:insert(?MODULE, {K, V}) + dict:fold(fun({Sec, Key} = K, V, _) -> + VExisting = get(Sec, Key, V), + ets:insert(?MODULE, {K, V}), + case V =:= VExisting of + true -> + ok; + false -> + couch_log:notice("Reload detected config change ~s.~s = ~p", [Sec, Key, V]), + Event = {config_change, Sec, Key, V, true}, + gen_event:sync_notify(config_event, Event) + end end, nil, DiskKVs), % And remove anything in ets that wasn't % on disk. - ets:foldl(fun({K, _}, _) -> + ets:foldl(fun({{Sec, Key} = K, _}, _) -> case dict:is_key(K, DiskKVs) of true -> ok; false -> - ets:delete(?MODULE, K) + couch_log:notice("Reload deleting in-memory config ~s.~s", [Sec, Key]), + ets:delete(?MODULE, K), + Event = {config_change, Sec, Key, deleted, true}, + gen_event:sync_notify(config_event, Event) end end, nil, ?MODULE), {reply, ok, Config}. diff --git a/test/config_tests.erl b/test/config_tests.erl index ac3c77e..fae0d43 100644 --- a/test/config_tests.erl +++ b/test/config_tests.erl @@ -293,7 +293,9 @@ config_notifier_behaviour_test_() -> {["section_foo"], fun should_not_notify/2}, {[{"section_foo", "key_bar"}], fun should_not_notify/2}, {all, fun should_unsubscribe_when_subscriber_gone/2}, - {all, fun should_not_add_duplicate/2} + {all, fun should_not_add_duplicate/2}, + {all, fun should_notify_on_config_reload/2}, + {all, fun should_notify_on_config_reload_flush/2} ] } }. @@ -707,6 +709,27 @@ should_keep_features_on_config_restart() -> with_process_restart(config), ?assertEqual([snek], config:features()). +should_notify_on_config_reload(Subscription, {_Apps, Pid}) -> + {to_string(Subscription), ?_test(begin + ?assertEqual(ok, config:set("section_foo", "key_bar", "any", true)), + ?assertEqual({config_change,"section_foo", "key_bar", "any", true}, getmsg(Pid)), + ?assertEqual(ok, config:set("section_foo", "key_bar", "not_any", false)), + ?assertEqual({config_change,"section_foo", "key_bar", "not_any", false}, getmsg(Pid)), + ?assertEqual(ok, config:reload()), + ?assertEqual({config_change,"section_foo", "key_bar", "any", true}, getmsg(Pid)), + ok + end)}. + +should_notify_on_config_reload_flush(Subscription, {_Apps, Pid}) -> + {to_string(Subscription), ?_test(begin + ?assertEqual(ok, config:set("section_foo_temp", "key_bar", "any", false)), + ?assertEqual({config_change,"section_foo_temp", "key_bar", "any", false}, getmsg(Pid)), + ?assertEqual(ok, config:reload()), + ?assertEqual({config_change,"section_foo_temp", "key_bar", deleted, true}, getmsg(Pid)), + ok + end)}. + + spawn_config_listener() -> Self = self(), Pid = erlang:spawn(fun() ->