Merge pull request #13 from apache/allow-for-dynamic-ioq-classes
Allow for dynamic ioq classes
diff --git a/IOQ2.md b/IOQ2.md
index ddf8d22..849fbe2 100644
--- a/IOQ2.md
+++ b/IOQ2.md
@@ -611,6 +611,16 @@
```
+### Dynamic IOQ classes
+
+To support 3rd party IO channels for things like search/geo/cache/etc, you can
+manually set a config priority for the desired class, and then it will be
+picked up by `ioq_config:is_valid_class/1`. Because the `ioq_config:set_*`
+setters depend on `is_valid_class`, you must manually define the priority
+initially, for example with `config:set("ioq.classes", "search", "1.0").`.
+Afterwards, you'll be able to utilize the setters as expected.
+
+
## ioq_server2:get_state
You can see a human readable representation of the IOQ2 server state with the
diff --git a/include/ioq.hrl b/include/ioq.hrl
index 55c95f8..499a140 100644
--- a/include/ioq.hrl
+++ b/include/ioq.hrl
@@ -19,6 +19,15 @@
-define(DISPATCH_SINGLE_SERVER, "single_server").
-define(DISPATCH_SERVER_PER_SCHEDULER, "server_per_scheduler").
+%% Config Categories
+-define(SHARD_CLASS_SEPARATOR, "||").
+-define(IOQ2_CONFIG, "ioq2").
+-define(IOQ2_BYPASS_CONFIG, "ioq2.bypass").
+-define(IOQ2_SHARDS_CONFIG, "ioq2.shards").
+-define(IOQ2_USERS_CONFIG, "ioq2.users").
+-define(IOQ2_CLASSES_CONFIG, "ioq2.classes").
+
+
-define(DEFAULT_CLASS_PRIORITIES, [
{customer, 1.0},
{internal_repl, 0.001},
diff --git a/src/ioq_config.erl b/src/ioq_config.erl
index 9cc2371..6b324e3 100644
--- a/src/ioq_config.erl
+++ b/src/ioq_config.erl
@@ -54,14 +54,6 @@
]).
--define(SHARD_CLASS_SEPARATOR, "||").
--define(IOQ2_CONFIG, "ioq2").
--define(IOQ2_BYPASS_CONFIG, "ioq2.bypass").
--define(IOQ2_SHARDS_CONFIG, "ioq2.shards").
--define(IOQ2_USERS_CONFIG, "ioq2.users").
--define(IOQ2_CLASSES_CONFIG, "ioq2.classes").
-
-
ioq_classes() ->
[Class || {Class, _Priority} <- ?DEFAULT_CLASS_PRIORITIES].
@@ -143,8 +135,19 @@
ok = set_config(?IOQ2_USERS_CONFIG, User, Value, Reason).
-is_valid_class(Class) ->
- lists:member(Class, ioq_classes()).
+is_valid_class(Class) when is_atom(Class) ->
+ case lists:member(Class, ioq_classes()) of
+ true ->
+ true;
+ false ->
+ SClass = atom_to_list(Class),
+ case config:get(?IOQ2_CLASSES_CONFIG, SClass, undefined) of
+ undefined ->
+ false;
+ _ ->
+ true
+ end
+ end.
check_float_value(Value) when is_float(Value) ->
diff --git a/test/ioq_config_tests.erl b/test/ioq_config_tests.erl
index a7fd491..2b6e153 100644
--- a/test/ioq_config_tests.erl
+++ b/test/ioq_config_tests.erl
@@ -260,3 +260,34 @@
ok = ioq_config:set_bypass(interactive, true, "Bypassing interactive"),
Value = config:get_boolean("ioq2.bypass", "interactive", false),
?_assertEqual(true, Value).
+
+
+valid_classes_test_() ->
+ {
+ "Test ioq_config is_valid_class logic",
+ {
+ foreach,
+ fun() -> test_util:start_applications([config, couch_log]) end,
+ fun(_) -> test_util:stop_applications([config, couch_log]) end,
+ [
+ fun check_default_classes/1,
+ fun check_undeclared_class/1,
+ fun check_declared_class/1
+ ]
+ }
+ }.
+
+
+check_default_classes(_) ->
+ Classes = [C || {C, _P} <- ?DEFAULT_CLASS_PRIORITIES],
+ [?_assert(ioq_config:is_valid_class(C)) || C <- Classes].
+
+
+check_undeclared_class(_) ->
+ ?_assert(not ioq_config:is_valid_class(search)).
+
+
+check_declared_class(_) ->
+ config:set(?IOQ2_CLASSES_CONFIG, "search", "1.0", false),
+ ?_assert(ioq_config:is_valid_class(search)).
+