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 2026/10/04 17:00:51 UTC
(couchdb) 04/12: Fixup nouveau out-of-order purge PR
This is an automated email from the ASF dual-hosted git repository.
nickva pushed a commit to branch 3.5.x-a-few-more-fixes
in repository https://gitbox.apache.org/repos/asf/couchdb.git
commit 1d6fcc14a37d51ee2fefafa32f99b2815df194eb
Author: Nick Vatamaniuc <va...@gmail.com>
AuthorDate: Fri Oct 2 14:41:19 2026 -0400
Fixup nouveau out-of-order purge PR
Implement the fixups from https://github.com/apache/couchdb/pull/6138
(cherry picked from commit dd14b1ade8d5fccecb074cc116391a6a47a5f953)
---
src/nouveau/src/nouveau_index_updater.erl | 43 ++++++++++++++++++++-----------
test/elixir/test/nouveau_test.exs | 13 ++++++++--
2 files changed, 39 insertions(+), 17 deletions(-)
diff --git a/src/nouveau/src/nouveau_index_updater.erl b/src/nouveau/src/nouveau_index_updater.erl
index 9f9de5844..5b03f35ab 100644
--- a/src/nouveau/src/nouveau_index_updater.erl
+++ b/src/nouveau/src/nouveau_index_updater.erl
@@ -244,29 +244,42 @@ purge_index(Db, Index, StartUpdateSeq, #purge_acc{} = PurgeAcc0) ->
case couch_db:get_full_doc_info(Db, Id) of
not_found ->
queue_purge(Id, PurgeSeq, PurgeAcc1);
- #full_doc_info{} = FDI ->
- #doc_info{high_seq = Seq} = couch_doc:to_doc_info(FDI),
+ #full_doc_info{update_seq = Seq} ->
+ %% FDI still exists. If it changed after index last saw it
+ %% (eg. doc was re-created, or a leaf was purged and all
+ %% leafs were re-labeled with new sequences), remove it and
+ %% let the changes phase index the winner (if there is a
+ %% new one). If the FDI didn't change, then the index
+ %% already has its current winner (this may be when purging
+ %% a non-leaf or non-existent revision).
case Seq > StartUpdateSeq of
- true ->
- queue_purge(Id, PurgeSeq, PurgeAcc1);
- false ->
- PurgeAcc1
+ true -> queue_purge(Id, PurgeSeq, PurgeAcc1);
+ false -> PurgeAcc1
end
end,
update_task(1),
- maybe_flush_batch(PurgeAcc2)
+ case maybe_flush_batch(PurgeAcc2) of
+ {ok, PurgeAcc3} ->
+ {ok, PurgeAcc3};
+ {error, Reason} ->
+ exit({error, Reason})
+ end
end,
- {ok, #purge_acc{} = PurgeAcc3} = couch_db:fold_purge_infos(
+ {ok, #purge_acc{} = PurgeAcc4} = couch_db:fold_purge_infos(
Db, PurgeAcc0#purge_acc.index_purge_seq, FoldFun, PurgeAcc0, []
),
- {ok, PurgeAcc4} = flush_batch(PurgeAcc3),
- DbPurgeSeq = couch_db:get_purge_seq(Db),
- ok = nouveau_api:set_purge_seq(
- Index, PurgeAcc4#purge_acc.index_purge_seq, DbPurgeSeq
- ),
- update_local_doc(Db, Index, DbPurgeSeq),
- ok.
+ case flush_batch(PurgeAcc4) of
+ {ok, PurgeAcc5} ->
+ DbPurgeSeq = couch_db:get_purge_seq(Db),
+ ok = nouveau_api:set_purge_seq(
+ Index, PurgeAcc5#purge_acc.index_purge_seq, DbPurgeSeq
+ ),
+ update_local_doc(Db, Index, DbPurgeSeq),
+ ok;
+ {error, Reason} ->
+ exit({error, Reason})
+ end.
queue_purge(Id, PurgeSeq, #purge_acc{} = PurgeAcc) ->
Item = nouveau_api:make_purge(
diff --git a/test/elixir/test/nouveau_test.exs b/test/elixir/test/nouveau_test.exs
index 9a589602b..8f52dba5f 100644
--- a/test/elixir/test/nouveau_test.exs
+++ b/test/elixir/test/nouveau_test.exs
@@ -721,14 +721,14 @@ defmodule NouveauTest do
assert get_total_hits(resp) == 4
# purge two docs in separate requests
- doc_a = (Enum.at(create_resp.body, 0))
+ doc_a = Enum.at(create_resp.body, 0)
resp =
Couch.post("/#{db_name}/_purge",
body: %{doc_a["id"] => [doc_a["rev"]]}
)
assert_status_code(resp, 201)
- doc_b = (Enum.at(create_resp.body, 1))
+ doc_b = Enum.at(create_resp.body, 1)
resp =
Couch.post("/#{db_name}/_purge",
body: %{doc_b["id"] => [doc_b["rev"]]}
@@ -751,6 +751,15 @@ defmodule NouveauTest do
assert_status_code(resp, 200)
assert get_total_hits(resp) == 5
+ # b (doc3) should have "foo" instead of "bar"
+ resp = Couch.get(search_url, query: %{q: "foo:bar"})
+ assert_status_code(resp, 200)
+ assert get_total_hits(resp) == 0
+
+ resp = Couch.get(search_url, query: %{q: "foo:foo"})
+ assert_status_code(resp, 200)
+ assert get_total_hits(resp) == 2
+
# confirm nouveau responds and has correct sequences
resp = Couch.get("/#{db_name}/_design/foo/_nouveau_info/bar")
assert_status_code(resp, 200)