summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Vatamaniuc <vatamane@apache.org>2018-02-21 17:41:56 -0500
committerNick Vatamaniuc <vatamane@apache.org>2018-02-21 19:57:43 -0500
commit16699e5b399044109ad946e6986323d8e5f6f140 (patch)
tree4f45ceff9cc5975b071bc7f313e4b212edefd588
parent302bd8b8b193186b920c56c918bb2bb7edc4be8a (diff)
downloadcouchdb-fix-noproc-in-replicator-put.tar.gz
Avoid unconditional retries in replicator's http clientfix-noproc-in-replicator-put
In some cases the higher level code from `couch_replicator_api_wrap` needs to handle retries explicitly and cannot cope with retries happening in the lower level http client. In such cases it sets `retries = 0`. For example: https://github.com/apache/couchdb/blob/master/src/couch_replicator/src/couch_replicator_api_wrap.erl#L271-L275 The http client then should avoid unconditional retries and instead consult `retries` value. If `retries = 0`, it shouldn't retry and instead bubble the exception up to the caller. This bug was discovered when attachments were replicated to a target cluster and the target cluster's resources were constrainted. Since attachment `PUT` requests were made from the context of an open_revs `GET` request, `PUT` request timed out, and they would retry. However, because the retry didn't bubble up to the `open_revs` code, the second `PUT` request would die with a `noproc` error, since the old parser had exited by then. See issue #745 for more.
-rw-r--r--src/couch_replicator/src/couch_replicator_httpc.erl7
1 files changed, 1 insertions, 6 deletions
diff --git a/src/couch_replicator/src/couch_replicator_httpc.erl b/src/couch_replicator/src/couch_replicator_httpc.erl
index d3c6b0179..45472f431 100644
--- a/src/couch_replicator/src/couch_replicator_httpc.erl
+++ b/src/couch_replicator/src/couch_replicator_httpc.erl
@@ -139,12 +139,7 @@ process_response({error, sel_conn_closed}, Worker, HttpDb, Params, _Cb) ->
%% next request.
process_response({error, connection_closing}, Worker, HttpDb, Params, _Cb) ->
stop_and_release_worker(HttpDb#httpdb.httpc_pool, Worker),
- throw({retry, HttpDb, Params});
-
-process_response({error, req_timedout}, _Worker, HttpDb, Params, _Cb) ->
- % ibrowse worker terminated because remote peer closed the socket
- % -> not an error
- throw({retry, HttpDb, Params});
+ maybe_retry({error, connection_closing}, Worker, HttpDb, Params);
process_response({ibrowse_req_id, ReqId}, Worker, HttpDb, Params, Callback) ->
process_stream_response(ReqId, Worker, HttpDb, Params, Callback);