diff options
author | iilyak <iilyak@ca.ibm.com> | 2018-08-08 07:27:37 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-08-08 07:27:37 -0700 |
commit | d98e3e1998e8d20bc580d495b82cc3a9b6c82dad (patch) | |
tree | 70f0566c42788424260536c2df00856c1bce5576 | |
parent | 54b2eaac0094c035a6855af3f1e1e0db07b02f93 (diff) | |
parent | 7a2a39007284039fb2744aa441fa2fd73af23170 (diff) | |
download | couchdb-d98e3e1998e8d20bc580d495b82cc3a9b6c82dad.tar.gz |
Merge pull request #1432 from cloudant/support-callback-module-data-provider
Support callback module data provider
-rw-r--r-- | src/couch_epi/README.md | 35 | ||||
-rw-r--r-- | src/couch_epi/src/couch_epi_data.erl | 11 | ||||
-rw-r--r-- | src/couch_epi/src/couch_epi_sup.erl | 5 | ||||
-rw-r--r-- | src/couch_epi/test/couch_epi_tests.erl | 67 |
4 files changed, 104 insertions, 14 deletions
diff --git a/src/couch_epi/README.md b/src/couch_epi/README.md index 66421ceb9..368ad9afd 100644 --- a/src/couch_epi/README.md +++ b/src/couch_epi/README.md @@ -39,7 +39,8 @@ could add an entry in its implementation of couch_epi_plugin behaviour: {priv_file, "stats_descriptions.cfg"}, [{interval, 5000}]} {{couch_stats, descriptions}, {file, "/tmp/extra_stats.cfg"}, [{interval, 5000}]}, - {{couch_stats, descriptions}, {module, my_stats}} + {{couch_stats, descriptions}, {static_module, my_stats}}, + {{couch_stats, descriptions}, {callback_module, my_stats}} ]. When service provider wants to learn about all the installed config data for it to use @@ -65,6 +66,38 @@ There are also additional functions to get the same data in various formats - `couch_epi:keys(Handle)` - returns list of configured keys - `couch_epi:subscribers(Handle)` - return list of known subscribers +The difference between `static_module` and `callback_module` providers is in how +couch_epi detects the changes. `static_module` is designed for the cases when you +have your data hardcoded in the module. For example you might have the following: + +``` +-export([data/0]). + +data() -> + [ + {[complex, key, 2], [ + {type, counter}, + {desc, bar} + ]}, + {[complex, key, 1], [ + {type, counter}, + {desc, updated_foo} + ]} + ]. +``` + +The changes are detected by relying on `vsn` module attribute. Therefore we +would notice the change only when data source module is recompiled. + +The `callback_module` provider uses the return value from `data/0` to detect +changes and it is useful for cases when the data term is constructed dynamically. +For example to cache values of CouchDB config one could use the following: + +``` +-export([data/0]). +data() -> + config:get("dreyfus"). +``` # Function dispatch example diff --git a/src/couch_epi/src/couch_epi_data.erl b/src/couch_epi/src/couch_epi_data.erl index bbed828bb..2bb09f6cf 100644 --- a/src/couch_epi/src/couch_epi_data.erl +++ b/src/couch_epi/src/couch_epi_data.erl @@ -102,12 +102,15 @@ definitions({file, FilePath}) -> {error, Reason} -> {error, {FilePath, Reason}} end; -definitions({module, Module}) when is_atom(Module) -> - definitions({module, [Module]}); -definitions({module, Modules}) -> +definitions({static_module, Module}) when is_atom(Module) -> + definitions({static_module, [Module]}); +definitions({static_module, Modules}) -> Data = lists:append([M:data() || M <- Modules]), Hash = couch_epi_functions_gen:hash(Modules), - {ok, Hash, Data}. + {ok, Hash, Data}; +definitions({callback_module, Module}) -> + Data = Module:data(), + {ok, erlang:phash2(Data), Data}. hash_of_file(FilePath) -> {ok, Data} = file:read_file(FilePath), diff --git a/src/couch_epi/src/couch_epi_sup.erl b/src/couch_epi/src/couch_epi_sup.erl index 31f27d752..509f5a1c2 100644 --- a/src/couch_epi/src/couch_epi_sup.erl +++ b/src/couch_epi/src/couch_epi_sup.erl @@ -121,7 +121,8 @@ modules(#couch_epi_spec{kind = services, value = Module}) -> [Module]; modules(#couch_epi_spec{kind = data_providers, value = Value}) -> case Value of - {module, Module} -> [Module]; + {static_module, Module} -> [Module]; + {callback_module, Module} -> [Module]; _ -> [] end; modules(#couch_epi_spec{kind = data_subscriptions, behaviour = Module}) -> @@ -159,7 +160,7 @@ services() -> data_providers() -> [ - {{test_app, descriptions}, {module, ?MODULE}, [{interval, 100}]} + {{test_app, descriptions}, {static_module, ?MODULE}, [{interval, 100}]} ]. data_subscriptions() -> diff --git a/src/couch_epi/test/couch_epi_tests.erl b/src/couch_epi/test/couch_epi_tests.erl index 79122d75a..042753215 100644 --- a/src/couch_epi/test/couch_epi_tests.erl +++ b/src/couch_epi/test/couch_epi_tests.erl @@ -17,7 +17,7 @@ -define(DATA_FILE1, ?ABS_PATH("test/fixtures/app_data1.cfg")). -define(DATA_FILE2, ?ABS_PATH("test/fixtures/app_data2.cfg")). --export([notify_cb/4, save/3]). +-export([notify_cb/4, save/3, get/2]). -record(ctx, {file, handle, pid, kv, key, modules = []}). @@ -83,6 +83,14 @@ ]. "). +-define(DATA_MODULE3(Name, Kv), " + -export([data/0]). + +data() -> + {ok, Data} = couch_epi_tests:get('" ++ atom_to_list(Kv) ++ "', data), + Data. +"). + %% ------------------------------------------------------------------ %% couch_epi_plugin behaviour %% ------------------------------------------------------------------ @@ -175,7 +183,7 @@ setup(data_file) -> handle = couch_epi:get_handle(Key), kv = KV, pid = Pid}; -setup(data_module) -> +setup(static_data_module) -> error_logger:tty(false), Key = {test_app, descriptions}, @@ -183,7 +191,7 @@ setup(data_module) -> ok = generate_module(provider, ?DATA_MODULE1(provider)), KV = start_state_storage(), - ok = start_epi([{provider_epi, plugin_module([KV, {module, provider}])}]), + ok = start_epi([{provider_epi, plugin_module([KV, {static_module, provider}])}]), Pid = whereis(couch_epi:get_handle(Key)), Handle = couch_epi:get_handle(Key), @@ -194,6 +202,33 @@ setup(data_module) -> modules = [Handle, provider], kv = KV, pid = Pid}; +setup(callback_data_module) -> + error_logger:tty(false), + + Key = {test_app, descriptions}, + + KV = start_state_storage(), + Value = [ + {[complex, key, 1], [ + {type, counter}, + {desc, foo} + ]} + ], + save(KV, data, Value), + + ok = generate_module(provider, ?DATA_MODULE3(provider, KV)), + + ok = start_epi([{provider_epi, plugin_module([KV, {callback_module, provider}])}]), + + Pid = whereis(couch_epi:get_handle(Key)), + Handle = couch_epi:get_handle(Key), + + #ctx{ + key = Key, + handle = Handle, + modules = [Handle, provider], + kv = KV, + pid = Pid}; setup(functions) -> Key = my_service, error_logger:tty(false), @@ -244,7 +279,8 @@ epi_config_update_test_() -> ], Cases = [ data_file, - data_module, + static_data_module, + callback_data_module, functions ], { @@ -264,7 +300,8 @@ epi_data_source_test_() -> ], Cases = [ data_file, - data_module + static_data_module, + callback_data_module ], { "epi data API tests", @@ -305,7 +342,8 @@ epi_providers_order_test_() -> epi_reload_test_() -> Cases = [ data_file, - data_module, + static_data_module, + callback_data_module, functions ], Funs = [ @@ -565,8 +603,21 @@ update(Case, #ctx{pid = Pid, modules = Modules} = Ctx) -> update_definitions(data_file, #ctx{file = File}) -> {ok, _} = file:copy(?DATA_FILE2, File), ok; -update_definitions(data_module, #ctx{}) -> +update_definitions(static_data_module, #ctx{}) -> ok = generate_module(provider, ?DATA_MODULE2(provider)); +update_definitions(callback_data_module, #ctx{kv = Kv}) -> + Value = [ + {[complex, key, 2], [ + {type, counter}, + {desc, bar} + ]}, + {[complex, key, 1], [ + {type, counter}, + {desc, updated_foo} + ]} + ], + save(Kv, data, Value), + ok; update_definitions(functions, #ctx{}) -> ok = generate_module(provider1, ?MODULE2(provider1)). @@ -597,6 +648,8 @@ save(Kv, Key, Value) -> call(Kv, {set, Key, Value}). get(#ctx{kv = Kv}, Key) -> + call(Kv, {get, Key}); +get(Kv, Key) -> call(Kv, {get, Key}). call(Server, Msg) -> |