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 2023/07/13 18:04:36 UTC

[couchdb] 01/01: [WIP] Do not skip over uknown 400 error on replication doc PUT

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

vatamane pushed a commit to branch replicator-skip-explicit-4xx-errors-only
in repository https://gitbox.apache.org/repos/asf/couchdb.git

commit b53855778133a43cf1b22604a82228df0b979d7b
Author: Nick Vatamaniuc <va...@gmail.com>
AuthorDate: Thu Jul 13 14:02:55 2023 -0400

    [WIP] Do not skip over uknown 400 error on replication doc PUT
    
    Issue: https://github.com/apache/couchdb/issues/4676
---
 src/chttpd/src/chttpd_db.erl                       |  3 +-
 .../src/couch_replicator_worker.erl                | 79 ++++++++++++----------
 2 files changed, 47 insertions(+), 35 deletions(-)

diff --git a/src/chttpd/src/chttpd_db.erl b/src/chttpd/src/chttpd_db.erl
index e2de301b2..8e377878d 100644
--- a/src/chttpd/src/chttpd_db.erl
+++ b/src/chttpd/src/chttpd_db.erl
@@ -1138,7 +1138,8 @@ db_doc_req(#httpd{method = 'PUT', user_ctx = Ctx} = Req, Db, DocId) ->
                     UpdateType
                 ),
                 WaitFun(),
-                send_json(Req, HttpCode, RespHeaders1, RespBody)
+                %send_json(Req, HttpCode, RespHeaders1, RespBody)
+                send_json(Req, 418, RespHeaders1, RespBody)
             catch
                 throw:Err ->
                     % Document rejected by a validate_doc_update function.
diff --git a/src/couch_replicator/src/couch_replicator_worker.erl b/src/couch_replicator/src/couch_replicator_worker.erl
index 46e4a6e94..0fb7057eb 100644
--- a/src/couch_replicator/src/couch_replicator_worker.erl
+++ b/src/couch_replicator/src/couch_replicator_worker.erl
@@ -583,44 +583,55 @@ handle_flush_docs_result({error, {bulk_docs_failed, _, _} = Err}, _, _) ->
 
 flush_doc(Target, #doc{id = Id, revs = {Pos, [RevId | _]}} = Doc) ->
     try couch_replicator_api_wrap:update_doc(Target, Doc, [], ?REPLICATED_CHANGES) of
-        {ok, _} ->
-            ok;
-        Error ->
-            couch_log:error(
-                "Replicator: error writing document `~s` to `~s`: ~s",
-                [Id, couch_replicator_api_wrap:db_uri(Target), couch_util:to_binary(Error)]
-            ),
-            Error
+        {ok, _} ->  ok;
+        Error -> handle_doc_write_error(Error, Target, Id, Pos, RevId)
     catch
-        throw:{missing_stub, _} = MissingStub ->
-            throw(MissingStub);
         throw:{Error, Reason} ->
-            couch_log:error(
-                "Replicator: couldn't write document `~s`, revision `~s`,"
-                " to target database `~s`. Error: `~s`, reason: `~s`.",
-                [
-                    Id,
-                    couch_doc:rev_to_str({Pos, RevId}),
-                    couch_replicator_api_wrap:db_uri(Target),
-                    to_binary(Error),
-                    to_binary(Reason)
-                ]
-            ),
-            {error, Error};
-        throw:Err ->
-            couch_log:error(
-                "Replicator: couldn't write document `~s`, revision `~s`,"
-                " to target database `~s`. Error: `~s`.",
-                [
-                    Id,
-                    couch_doc:rev_to_str({Pos, RevId}),
-                    couch_replicator_api_wrap:db_uri(Target),
-                    to_binary(Err)
-                ]
-            ),
-            {error, Err}
+            handle_doc_write_error({Error, Reason}, Target, Id, Pos, RevId)
     end.
 
+% In most cases we fail the replication job by re-throwing the error.
+% The only exceptions are
+%  401 : unauthorized
+%  403 : forbidden
+%  413 : request_body_too_large
+%
+handle_doc_write_error({missing_stub, _} = MissingStub, _, _, _, _) ->
+    throw(MissingStub);
+handle_doc_write_error({error, request_body_too_large} = Error, Target, Id, _, _) ->
+    couch_log:error(
+        "Replicator: skipping writing document `~s` to `~s` : request_body_too_large.",
+        [Id, couch_replicator_api_wrap:db_uri(Target)]
+    ),
+    Error;
+handle_doc_write_error({Error, Reason}, Target, Id, Pos, RevId) when
+    Error == unauthorized orelse Error == forbidden
+->
+    couch_log:error(
+        "Replicator: skipping writing document `~s`, revision `~s`,"
+        " to target database `~s`. Error: `~s`, reason: `~s`.",
+        [
+            Id,
+            couch_doc:rev_to_str({Pos, RevId}),
+            couch_replicator_api_wrap:db_uri(Target),
+            to_binary(Error),
+            to_binary(Reason)
+        ]
+    ),
+    {error, Error};
+handle_doc_write_error(Err, Target, Id, Pos, RevId) ->
+     couch_log:error(
+         "Replicator: error writting document `~s`, revision `~s`,"
+         " to target database `~s`. Error: `~s`.",
+         [
+             Id,
+             couch_doc:rev_to_str({Pos, RevId}),
+             couch_replicator_api_wrap:db_uri(Target),
+             to_binary(Err)
+        ]
+    ),
+    throw(Err).
+
 find_missing(DocInfos, Target, Parent, #fetch_stats{} = St) ->
     {IdRevs, AllCount} = lists:foldr(
         fun