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 2022/06/06 19:26:42 UTC
[couchdb] 01/01: Handle all_dbs_active in fabric_doc_update
This is an automated email from the ASF dual-hosted git repository.
vatamane pushed a commit to branch handle_all_dbs_active_in_fabric_doc_update
in repository https://gitbox.apache.org/repos/asf/couchdb.git
commit 6fac7cc63291aeba9edac80c0c40162944d6b6e9
Author: Nick Vatamaniuc <va...@gmail.com>
AuthorDate: Mon Jun 6 15:22:14 2022 -0400
Handle all_dbs_active in fabric_doc_update
Previously fabric_doc_update message handler crashed with a function_clause
error the first time it encountered an all_dbs_active error.
Opt to handle it as a `rexi_EXIT` with a hope at that some workers would still
return a valid result.
---
src/fabric/src/fabric_doc_update.erl | 66 ++++++++++++++++++++++++++++++++++++
1 file changed, 66 insertions(+)
diff --git a/src/fabric/src/fabric_doc_update.erl b/src/fabric/src/fabric_doc_update.erl
index 69ad03da5..9de9c6580 100644
--- a/src/fabric/src/fabric_doc_update.erl
+++ b/src/fabric/src/fabric_doc_update.erl
@@ -66,6 +66,11 @@ handle_message({rexi_EXIT, _}, Worker, Acc0) ->
{WC, LenDocs, W, GrpDocs, DocReplyDict} = Acc0,
NewGrpDocs = lists:keydelete(Worker, 1, GrpDocs),
skip_message({WC - 1, LenDocs, W, NewGrpDocs, DocReplyDict});
+handle_message({error, all_dbs_active}, Worker, Acc0) ->
+ % treat it like rexi_EXIT, the hope at least one copy will return successfully
+ {WC, LenDocs, W, GrpDocs, DocReplyDict} = Acc0,
+ NewGrpDocs = lists:keydelete(Worker, 1, GrpDocs),
+ skip_message({WC - 1, LenDocs, W, NewGrpDocs, DocReplyDict});
handle_message(internal_server_error, Worker, Acc0) ->
% happens when we fail to load validation functions in an RPC worker
{WC, LenDocs, W, GrpDocs, DocReplyDict} = Acc0,
@@ -329,6 +334,8 @@ doc_update_test_() ->
fun doc_update1/0,
fun doc_update2/0,
fun doc_update3/0,
+ fun handle_all_dbs_active/0,
+ fun handle_two_all_dbs_actives/0,
fun one_forbid/0,
fun two_forbid/0,
fun extend_tree_forbid/0,
@@ -467,6 +474,65 @@ doc_update3() ->
?assertEqual({ok, [{Doc1, {ok, Doc1}}, {Doc2, {ok, Doc2}}]}, Reply).
+handle_all_dbs_active() ->
+ Doc1 = #doc{revs = {1, [<<"foo">>]}},
+ Doc2 = #doc{revs = {1, [<<"bar">>]}},
+ Docs = [Doc1, Doc2],
+ Shards =
+ mem3_util:create_partition_map("foo", 3, 1, ["node1", "node2", "node3"]),
+ GroupedDocs = group_docs_by_shard_hack(<<"foo">>, Shards, Docs),
+ Acc0 = {
+ length(Shards),
+ length(Docs),
+ list_to_integer("2"),
+ GroupedDocs,
+ dict:from_list([{Doc, []} || Doc <- Docs])
+ },
+
+ {ok, {WaitingCount1, _, _, _, _} = Acc1} =
+ handle_message({ok, [{ok, Doc1}, {ok, Doc2}]}, hd(Shards), Acc0),
+ ?assertEqual(WaitingCount1, 2),
+
+ {ok, {WaitingCount2, _, _, _, _} = Acc2} =
+ handle_message({error, all_dbs_active}, lists:nth(2, Shards), Acc1),
+ ?assertEqual(WaitingCount2, 1),
+
+ {stop, Reply} =
+ handle_message({ok, [{ok, Doc1}, {ok, Doc2}]}, lists:nth(3, Shards), Acc2),
+
+ ?assertEqual({ok, [{Doc1, {ok, Doc1}}, {Doc2, {ok, Doc2}}]}, Reply).
+
+handle_two_all_dbs_actives() ->
+ Doc1 = #doc{revs = {1, [<<"foo">>]}},
+ Doc2 = #doc{revs = {1, [<<"bar">>]}},
+ Docs = [Doc1, Doc2],
+ Shards =
+ mem3_util:create_partition_map("foo", 3, 1, ["node1", "node2", "node3"]),
+ GroupedDocs = group_docs_by_shard_hack(<<"foo">>, Shards, Docs),
+ Acc0 = {
+ length(Shards),
+ length(Docs),
+ list_to_integer("2"),
+ GroupedDocs,
+ dict:from_list([{Doc, []} || Doc <- Docs])
+ },
+
+ {ok, {WaitingCount1, _, _, _, _} = Acc1} =
+ handle_message({ok, [{ok, Doc1}, {ok, Doc2}]}, hd(Shards), Acc0),
+ ?assertEqual(WaitingCount1, 2),
+
+ {ok, {WaitingCount2, _, _, _, _} = Acc2} =
+ handle_message({error, all_dbs_active}, lists:nth(2, Shards), Acc1),
+ ?assertEqual(WaitingCount2, 1),
+
+ {stop, Reply} =
+ handle_message({error, all_dbs_active}, lists:nth(3, Shards), Acc2),
+
+ ?assertEqual(
+ {accepted, [{Doc1, {accepted, Doc1}}, {Doc2, {accepted, Doc2}}]},
+ Reply
+ ).
+
one_forbid() ->
Doc1 = #doc{revs = {1, [<<"foo">>]}},
Doc2 = #doc{revs = {1, [<<"bar">>]}},