Skip to content

Commit

Permalink
Avoid unconditional retries in replicator's http client
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
nickva committed Feb 21, 2018
1 parent 302bd8b commit 399c07b
Showing 1 changed file with 3 additions and 3 deletions.
6 changes: 3 additions & 3 deletions src/couch_replicator/src/couch_replicator_httpc.erl
Original file line number Diff line number Diff line change
Expand Up @@ -139,12 +139,12 @@ 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});
maybe_retry({error, connection_closing}, Worker, HttpDb, Params);

process_response({error, req_timedout}, _Worker, HttpDb, Params, _Cb) ->
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, req_timedout}, Worker, HttpDb, Params);

process_response({ibrowse_req_id, ReqId}, Worker, HttpDb, Params, Callback) ->
process_stream_response(ReqId, Worker, HttpDb, Params, Callback);
Expand Down

0 comments on commit 399c07b

Please sign in to comment.