You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by va...@apache.org on 2024/10/30 00:53:43 UTC

(couchdb) 01/01: Allow online js_engine reconfiguration

This is an automated email from the ASF dual-hosted git repository.

vatamane pushed a commit to branch dynamic-quick-reconf
in repository https://gitbox.apache.org/repos/asf/couchdb.git

commit dcd8f00fd4ad1d9e400ff10031490c7db0f62cba
Author: Nick Vatamaniuc <va...@gmail.com>
AuthorDate: Tue Oct 29 20:50:53 2024 -0400

    Allow online js_engine reconfiguration
    
    This should make it possible to toggle between engines without having to
    restart the node.
    
    We already had a config listener so make sure it also sets up the js_engine
    bits, as well.
    
    Add a test to demonstrate it works both when setting a non-default value and
    reverting back to the default value.
---
 src/couch/src/couch_proc_manager.erl           | 19 ++++++---
 src/couch_quickjs/test/couch_quickjs_tests.erl | 53 +++++++++++++++++++++++++-
 2 files changed, 64 insertions(+), 8 deletions(-)

diff --git a/src/couch/src/couch_proc_manager.erl b/src/couch/src/couch_proc_manager.erl
index 885a438f7..81739bf09 100644
--- a/src/couch/src/couch_proc_manager.erl
+++ b/src/couch/src/couch_proc_manager.erl
@@ -139,11 +139,7 @@ init([]) ->
     % Lang -> number of procs spawn for that lang
     ets:new(?COUNTERS, [named_table]),
 
-    ets:insert(?SERVERS, get_servers_from_env("COUCHDB_QUERY_SERVER_")),
-    ets:insert(?SERVERS, get_servers_from_env("COUCHDB_NATIVE_QUERY_SERVER_")),
-    ets:insert(?SERVERS, [{"QUERY", {mango_native_proc, start_link, []}}]),
-    maybe_configure_erlang_native_servers(),
-    configure_js_engine(couch_server:get_js_engine()),
+    ok = configure_language_servers(),
 
     {ok, #state{
         config = get_proc_config(),
@@ -221,7 +217,7 @@ handle_cast(reload_config, State) ->
         hard_limit = get_hard_limit(),
         soft_limit = get_soft_limit()
     },
-    maybe_configure_erlang_native_servers(),
+    ok = configure_language_servers(),
     lists:foreach(
         fun({Lang, _}) ->
             ok = flush_waiters(NewState, Lang)
@@ -290,6 +286,9 @@ handle_config_change("native_query_servers", _, _, _, _) ->
 handle_config_change("query_server_config", _, _, _, _) ->
     gen_server:cast(?MODULE, reload_config),
     {ok, undefined};
+handle_config_change("couchdb", "js_engine", _, _, _) ->
+    gen_server:cast(?MODULE, reload_config),
+    {ok, undefined};
 handle_config_change(_, _, _, _, _) ->
     {ok, undefined}.
 
@@ -512,6 +511,14 @@ get_servers_from_env(Spec) ->
         os:getenv()
     ).
 
+configure_language_servers() ->
+    ets:insert(?SERVERS, get_servers_from_env("COUCHDB_QUERY_SERVER_")),
+    ets:insert(?SERVERS, get_servers_from_env("COUCHDB_NATIVE_QUERY_SERVER_")),
+    ets:insert(?SERVERS, [{"QUERY", {mango_native_proc, start_link, []}}]),
+    maybe_configure_erlang_native_servers(),
+    configure_js_engine(couch_server:get_js_engine()),
+    ok.
+
 get_query_server(LangStr) ->
     case ets:lookup(?SERVERS, string:to_upper(LangStr)) of
         [{_, Command}] -> Command;
diff --git a/src/couch_quickjs/test/couch_quickjs_tests.erl b/src/couch_quickjs/test/couch_quickjs_tests.erl
index b1089e3e5..44af444cd 100644
--- a/src/couch_quickjs/test/couch_quickjs_tests.erl
+++ b/src/couch_quickjs/test/couch_quickjs_tests.erl
@@ -18,7 +18,9 @@ setup() ->
     test_util:start_couch().
 
 teardown(Ctx) ->
-    config:delete("quickjs", "memory_limit_bytes", _Persist = false),
+    Persist = false,
+    config:delete("quickjs", "memory_limit_bytes", Persist),
+    config:delete("couchdb", "js_engine", Persist),
     test_util:stop_couch(Ctx).
 
 quickjs_test_() ->
@@ -30,7 +32,8 @@ quickjs_test_() ->
             ?TDEF_FE(t_get_mainjs_cmd),
             ?TDEF_FE(t_get_coffee_cmd),
             ?TDEF_FE(t_can_configure_memory_limit),
-            ?TDEF_FE(t_bad_memory_limit)
+            ?TDEF_FE(t_bad_memory_limit),
+            ?TDEF_FE(t_couch_jsengine_config_triggers_proc_server_reload)
         ]
     }.
 
@@ -60,9 +63,55 @@ t_bad_memory_limit(_) ->
     ?assertEqual(ExpectCmd, string:find(Cmd, ExpectCmd)),
     ?assertEqual(1, os_cmd(Cmd ++ " -V")).
 
+t_couch_jsengine_config_triggers_proc_server_reload(_) ->
+    case couch_server:with_spidermonkey() of
+        false ->
+            % Spidermonkey is not in the build at all, skip the test
+            ok;
+        true ->
+            OldVal = get_proc_manager_default_js(),
+            % In the test, set the engine to whatever is not the default
+            Toggle =
+                case couch_server:get_js_engine() of
+                    <<"quickjs">> -> "spidermonkey";
+                    <<"spidermonkey">> -> "quickjs"
+                end,
+
+            config:set("couchdb", "js_engine", Toggle, false),
+            % couch_server:get_js_engine/0 should be visible immediately
+            ?assertEqual(list_to_binary(Toggle), couch_server:get_js_engine()),
+
+            wait_until_proc_manager_updates(OldVal),
+            ?assertNotEqual(OldVal, get_proc_manager_default_js()),
+            NewVal = get_proc_manager_default_js(),
+
+            % Toggle back to the original default (test config:delete/3)
+            config:delete("couchdb", "js_engine", false),
+            wait_until_proc_manager_updates(NewVal),
+            ?assertNotEqual(NewVal, get_proc_manager_default_js()),
+            % We should be back to the original default
+            ?assertEqual(OldVal, get_proc_manager_default_js())
+    end.
+
 os_cmd(Cmd) ->
     Opts = [stream, {line, 4096}, binary, exit_status, hide],
     Port = open_port({spawn, Cmd}, Opts),
     receive
         {Port, {exit_status, Status}} -> Status
     end.
+
+wait_until_proc_manager_updates(OldVal) ->
+    WaitFun = fun() ->
+        case get_proc_manager_default_js() of
+            OldVal -> wait;
+            _ -> ok
+        end
+    end,
+    case test_util:wait(WaitFun, 5000) of
+        timeout -> error(timeout);
+        _ -> ok
+    end.
+
+get_proc_manager_default_js() ->
+    [{"JAVASCRIPT", Val}] = ets:lookup(couch_proc_manager_servers, "JAVASCRIPT"),
+    Val.