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

rnewson pushed a commit to branch nouveau-search-opt
in repository https://gitbox.apache.org/repos/asf/couchdb.git

commit 08181db4b7e881c91c1113c8326a9124d2038b5f
Author: Robert Newson <[email protected]>
AuthorDate: Tue Aug 5 12:36:33 2025 +0100

    optimize searches when index is fresh
    
    Send the search request first and use the 409 Conflict response
    to trigger index update (as long as query param 'update' is not
    set to false).
---
 src/nouveau/src/nouveau_rpc.erl | 51 +++++++++++++++++++++++++----------------
 1 file changed, 31 insertions(+), 20 deletions(-)

diff --git a/src/nouveau/src/nouveau_rpc.erl b/src/nouveau/src/nouveau_rpc.erl
index e0b863f87..7cfe317ef 100644
--- a/src/nouveau/src/nouveau_rpc.erl
+++ b/src/nouveau/src/nouveau_rpc.erl
@@ -24,6 +24,8 @@
 -include("nouveau.hrl").
 -import(nouveau_util, [index_path/1]).
 
+-define(nouveau_update_latency, nouveau_update_latency).
+
 search(DbName, #index{} = Index0, QueryArgs0) ->
     %% Incorporate the shard name into the record.
     Index1 = Index0#index{dbname = DbName},
@@ -47,33 +49,42 @@ search(DbName, #index{} = Index0, QueryArgs0) ->
                 }
         end,
 
-    %% check if index is up to date
-    T0 = erlang:monotonic_time(),
-    case Update andalso nouveau_index_updater:outdated(Index1) of
-        true ->
-            case nouveau_index_manager:update_index(Index1) of
+    %% Run the search
+    case nouveau_api:search(Index1, QueryArgs1) of
+        {ok, Response} ->
+            rexi:reply({ok, Response#{update_latency => 
get_update_latency()}});
+        {error, stale_index} when Update ->
+            %% update the index and try again
+            case update_stale_index(Index1) of
                 ok ->
-                    ok;
+                    search(DbName, Index0, QueryArgs0);
                 {error, Reason} ->
                     rexi:reply({error, Reason})
             end;
-        false ->
+        Else ->
+            rexi:reply(Else)
+    end.
+
+update_stale_index(#index{} = Index) ->
+    T0 = erlang:monotonic_time(),
+    case nouveau_index_manager:update_index(Index) of
+        ok ->
+            T1 = erlang:monotonic_time(),
+            erlang:put(
+                ?nouveau_update_latency,
+                get_update_latency() + erlang:convert_time_unit(T1 - T0, 
native, millisecond)
+            ),
             ok;
         {error, Reason} ->
-            rexi:reply({error, Reason})
-    end,
-    T1 = erlang:monotonic_time(),
-    UpdateLatency = erlang:convert_time_unit(T1 - T0, native, millisecond),
+            {error, Reason}
+    end.
 
-    %% Run the search
-    case nouveau_api:search(Index1, QueryArgs1) of
-        {ok, Response} ->
-            rexi:reply({ok, Response#{update_latency => UpdateLatency}});
-        {error, stale_index} ->
-            %% try again.
-            search(DbName, Index0, QueryArgs0);
-        Else ->
-            rexi:reply(Else)
+get_update_latency() ->
+    case erlang:get(?nouveau_update_latency) of
+        undefined ->
+            0;
+        UpdateLatency when is_integer(UpdateLatency) ->
+            UpdateLatency
     end.
 
 info(DbName, #index{} = Index0) ->

Reply via email to