summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Vatamaniuc <vatamane@gmail.com>2023-01-09 12:02:36 -0500
committerNick Vatamaniuc <nickva@users.noreply.github.com>2023-01-09 12:55:02 -0500
commitfb3517936faf7f1ea33bd457e0b2f8a4202ee15a (patch)
treed0216eddbbacc3e29e147f30c4f0399747a48db1
parentca791828cd147590f83f31c4c4af6716ffafba90 (diff)
downloadcouchdb-fb3517936faf7f1ea33bd457e0b2f8a4202ee15a.tar.gz
Fix handling forbidden exceptions from workers in fabric_doc_update
Previously we handled `{bad_request, Msg}` but not `{forbidden, Msg}`, so a `before_doc_update` handler which wanted to emulate the VDU `forbidden` response ended up crashing with an unhandled clause instead. (Note: The replicator doc validation BDU wasn't affected as those BDU calls are made directly from fabric since `*_replicator` shards are "special" system dbs).
-rw-r--r--src/fabric/src/fabric_doc_update.erl20
1 files changed, 19 insertions, 1 deletions
diff --git a/src/fabric/src/fabric_doc_update.erl b/src/fabric/src/fabric_doc_update.erl
index b7b9e5972..77b424911 100644
--- a/src/fabric/src/fabric_doc_update.erl
+++ b/src/fabric/src/fabric_doc_update.erl
@@ -110,6 +110,8 @@ handle_message({not_found, no_db_file} = X, Worker, Acc0) ->
handle_message({ok, [X || _D <- Docs]}, Worker, Acc0);
handle_message({bad_request, Msg}, _, _) ->
throw({bad_request, Msg});
+handle_message({forbidden, Msg}, _, _) ->
+ throw({forbidden, Msg});
handle_message({request_entity_too_large, Entity}, _, _) ->
throw({request_entity_too_large, Entity}).
@@ -351,7 +353,8 @@ doc_update_test_() ->
fun extend_tree_forbid/0,
fun other_errors_one_forbid/0,
fun one_error_two_forbid/0,
- fun one_success_two_forbid/0
+ fun one_success_two_forbid/0,
+ fun worker_before_doc_update_forbidden/0
]
}.
@@ -751,6 +754,21 @@ one_success_two_forbid() ->
{error, [{Doc1, {ok, Doc1}}, {Doc2, {Doc2, {forbidden, <<"not allowed">>}}}]}, Reply
).
+worker_before_doc_update_forbidden() ->
+ Doc1 = #doc{revs = {1, [<<"foo">>]}},
+ Docs = [Doc1],
+ Shards =
+ mem3_util:create_partition_map("foo", 3, 1, ["node1", "node2", "node3"]),
+ GroupedDocs = group_docs_by_shard_hack(<<"foo">>, Shards, Docs),
+ Acc = {
+ length(Shards),
+ length(Docs),
+ list_to_integer("2"),
+ GroupedDocs,
+ dict:from_list([{Doc, []} || Doc <- Docs])
+ },
+ ?assertThrow({forbidden, <<"msg">>}, handle_message({forbidden, <<"msg">>}, hd(Shards), Acc)).
+
% needed for testing to avoid having to start the mem3 application
group_docs_by_shard_hack(_DbName, Shards, Docs) ->
dict:to_list(