Skip to content

Commit f224521

Browse files
authored
Merge pull request #5617 from apache/nouveau-search-opt
Nouveau search optimization
2 parents de46fea + 8276e37 commit f224521

File tree

3 files changed

+59
-30
lines changed

3 files changed

+59
-30
lines changed

src/nouveau/src/nouveau_rpc.erl

Lines changed: 40 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -24,45 +24,56 @@
2424
-include("nouveau.hrl").
2525
-import(nouveau_util, [index_path/1]).
2626

27-
search(DbName, #index{} = Index0, QueryArgs0) ->
27+
search(DbName, #index{} = Index, #{} = QueryArgs) ->
28+
search(DbName, #index{} = Index, QueryArgs, 0).
29+
30+
search(DbName, #index{} = Index0, QueryArgs0, UpdateLatency) ->
2831
%% Incorporate the shard name into the record.
2932
Index1 = Index0#index{dbname = DbName},
3033

31-
%% get minimum seqs for search
32-
{MinUpdateSeq, MinPurgeSeq} = nouveau_index_updater:get_db_info(Index1),
34+
Update = maps:get(update, QueryArgs0, true),
3335

3436
%% Incorporate min seqs into the query args.
35-
QueryArgs1 = QueryArgs0#{
36-
min_update_seq => MinUpdateSeq,
37-
min_purge_seq => MinPurgeSeq
38-
},
39-
Update = maps:get(update, QueryArgs1, true),
40-
41-
%% check if index is up to date
42-
T0 = erlang:monotonic_time(),
43-
case Update andalso nouveau_index_updater:outdated(Index1) of
44-
true ->
45-
case nouveau_index_manager:update_index(Index1) of
46-
ok ->
47-
ok;
48-
{error, Reason} ->
49-
rexi:reply({error, Reason})
50-
end;
51-
false ->
52-
ok;
53-
{error, Reason} ->
54-
rexi:reply({error, Reason})
55-
end,
56-
T1 = erlang:monotonic_time(),
57-
UpdateLatency = erlang:convert_time_unit(T1 - T0, native, millisecond),
37+
QueryArgs1 =
38+
case Update of
39+
true ->
40+
%% get minimum seqs for search
41+
{MinUpdateSeq, MinPurgeSeq} = nouveau_index_updater:get_db_info(Index1),
42+
QueryArgs0#{
43+
min_update_seq => MinUpdateSeq,
44+
min_purge_seq => MinPurgeSeq
45+
};
46+
false ->
47+
QueryArgs0#{
48+
min_update_seq => 0,
49+
min_purge_seq => 0
50+
}
51+
end,
5852

5953
%% Run the search
6054
case nouveau_api:search(Index1, QueryArgs1) of
6155
{ok, Response} ->
6256
rexi:reply({ok, Response#{update_latency => UpdateLatency}});
63-
{error, stale_index} ->
64-
%% try again.
65-
search(DbName, Index0, QueryArgs0);
57+
{error, stale_index} when Update ->
58+
update_and_retry(DbName, Index0, QueryArgs0, UpdateLatency);
59+
{error, {not_found, _}} when Update ->
60+
update_and_retry(DbName, Index0, QueryArgs0, UpdateLatency);
61+
Else ->
62+
rexi:reply(Else)
63+
end.
64+
65+
update_and_retry(DbName, Index, QueryArgs, UpdateLatency) ->
66+
T0 = erlang:monotonic_time(),
67+
case nouveau_index_manager:update_index(Index#index{dbname = DbName}) of
68+
ok ->
69+
T1 = erlang:monotonic_time(),
70+
search(
71+
DbName,
72+
Index,
73+
QueryArgs,
74+
UpdateLatency +
75+
erlang:convert_time_unit(T1 - T0, native, millisecond)
76+
);
6677
Else ->
6778
rexi:reply(Else)
6879
end.

test/elixir/test/config/nouveau.elixir

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
"purge with conflicts",
3131
"index same field with different field types",
3232
"index not found",
33-
"meta"
33+
"meta",
34+
"stale search"
3435
]
3536
}

test/elixir/test/nouveau_test.exs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -694,6 +694,23 @@ defmodule NouveauTest do
694694
assert resp.body["update_latency"] > 0
695695
end
696696

697+
@tag :with_db
698+
test "stale search", context do
699+
db_name = context[:db_name]
700+
url = "/#{db_name}/_design/foo/_nouveau/bar"
701+
create_ddoc(db_name)
702+
703+
resp = Couch.get(url, query: %{q: "*:*", update: false, include_docs: true})
704+
assert_status_code(resp, 404)
705+
706+
create_search_docs(db_name)
707+
resp = Couch.get(url, query: %{q: "*:*", include_docs: true})
708+
assert_status_code(resp, 200)
709+
ids = get_ids(resp)
710+
# nouveau sorts by _id as tie-breaker
711+
assert ids == ["doc1", "doc2", "doc3", "doc4"]
712+
end
713+
697714
def seq(str) do
698715
String.to_integer(hd(Regex.run(~r/^[0-9]+/, str)))
699716
end

0 commit comments

Comments
 (0)