diff options
author | Nick Vatamaniuc <vatamane@apache.org> | 2018-02-21 17:41:56 -0500 |
---|---|---|
committer | Nick Vatamaniuc <nickva@users.noreply.github.com> | 2018-02-21 21:34:04 -0500 |
commit | 6d959a7acab7d0ff110c7799f3295b6193f45c2f (patch) | |
tree | 4f45ceff9cc5975b071bc7f313e4b212edefd588 | |
parent | 302bd8b8b193186b920c56c918bb2bb7edc4be8a (diff) | |
download | couchdb-6d959a7acab7d0ff110c7799f3295b6193f45c2f.tar.gz |
Avoid unconditional retries in replicator's http client
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.erl | 7 |
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); |