You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by ja...@apache.org on 2010/02/27 00:43:38 UTC
svn commit: r916869 - in /couchdb/branches/0.11.x: THANKS
src/couchdb/couch_rep_att.erl src/couchdb/couch_rep_changes_feed.erl
Author: jan
Date: Fri Feb 26 23:43:38 2010
New Revision: 916869
URL: http://svn.apache.org/viewvc?rev=916869&view=rev
Log:
Avoid replication task crashes by imporoving timeout handling.
Closes COUCHDB-597.
Patch by Randall Leeds.
Modified:
couchdb/branches/0.11.x/THANKS
couchdb/branches/0.11.x/src/couchdb/couch_rep_att.erl
couchdb/branches/0.11.x/src/couchdb/couch_rep_changes_feed.erl
Modified: couchdb/branches/0.11.x/THANKS
URL: http://svn.apache.org/viewvc/couchdb/branches/0.11.x/THANKS?rev=916869&r1=916868&r2=916869&view=diff
==============================================================================
--- couchdb/branches/0.11.x/THANKS (original)
+++ couchdb/branches/0.11.x/THANKS Fri Feb 26 23:43:38 2010
@@ -50,5 +50,6 @@
* Joel Clark <un...@yahoo.com>
* Matt Lyon <ma...@flowerpowered.com>
* mikeal <mi...@gmail.com>
+ * Randall Leeds <ra...@gmail.com>
For a list of authors see the `AUTHORS` file.
Modified: couchdb/branches/0.11.x/src/couchdb/couch_rep_att.erl
URL: http://svn.apache.org/viewvc/couchdb/branches/0.11.x/src/couchdb/couch_rep_att.erl?rev=916869&r1=916868&r2=916869&view=diff
==============================================================================
--- couchdb/branches/0.11.x/src/couchdb/couch_rep_att.erl (original)
+++ couchdb/branches/0.11.x/src/couchdb/couch_rep_att.erl Fri Feb 26 23:43:38 2010
@@ -25,7 +25,11 @@
qs = [{rev, couch_doc:rev_to_str({Pos,RevId})}]
},
Ref = make_ref(),
- RcvFun = fun() -> attachment_receiver(Ref, Request) end,
+ RcvFun = fun() ->
+ Bin = attachment_receiver(Ref, Request),
+ cleanup(),
+ Bin
+ end,
Attachment#att{data=RcvFun}.
cleanup() ->
@@ -34,6 +38,8 @@
%% TODO maybe log, didn't expect to have data here
cleanup();
{ibrowse_async_response_end, _} ->
+ cleanup();
+ {ibrowse_async_headers, _, _, _} ->
cleanup()
after 0 ->
erase(),
@@ -43,13 +49,27 @@
% internal funs
attachment_receiver(Ref, Request) ->
- case get(Ref) of
+ try case get(Ref) of
undefined ->
{ReqId, ContentEncoding} = start_http_request(Request),
put(Ref, {ReqId, ContentEncoding}),
receive_data(Ref, ReqId, ContentEncoding);
{ReqId, ContentEncoding} ->
receive_data(Ref, ReqId, ContentEncoding)
+ end
+ catch
+ throw:{attachment_request_failed, timeout} ->
+ case {Request#http_db.retries, Request#http_db.pause} of
+ {0, _} ->
+ ?LOG_INFO("request for ~p failed", [Request#http_db.resource]),
+ throw({attachment_request_failed, max_retries_reached});
+ {N, Pause} when N > 0 ->
+ ?LOG_INFO("request for ~p timed out, retrying in ~p seconds",
+ [Request#http_db.resource, Pause/1000]),
+ timer:sleep(Pause),
+ cleanup(),
+ attachment_receiver(Ref, Request#http_db{retries = N-1})
+ end
end.
receive_data(Ref, ReqId, ContentEncoding) ->
@@ -71,6 +91,8 @@
{ibrowse_async_response_end, ReqId} ->
?LOG_ERROR("streaming att. ended but more data requested ~p", [ReqId]),
throw({attachment_request_failed, premature_end})
+ after 31000 ->
+ throw({attachment_request_failed, timeout})
end.
start_http_request(Req) ->
@@ -84,6 +106,8 @@
{ok, ContentEncoding, NewReqId} ->
{NewReqId, ContentEncoding}
end
+ after 10000 ->
+ throw({attachment_request_failed, timeout})
end.
validate_headers(_Req, 200, Headers) ->
Modified: couchdb/branches/0.11.x/src/couchdb/couch_rep_changes_feed.erl
URL: http://svn.apache.org/viewvc/couchdb/branches/0.11.x/src/couchdb/couch_rep_changes_feed.erl?rev=916869&r1=916868&r2=916869&view=diff
==============================================================================
--- couchdb/branches/0.11.x/src/couchdb/couch_rep_changes_feed.erl (original)
+++ couchdb/branches/0.11.x/src/couchdb/couch_rep_changes_feed.erl Fri Feb 26 23:43:38 2010
@@ -40,7 +40,9 @@
gen_server:start_link(?MODULE, [Parent, Source, StartSeq, PostProps], []).
next(Server) ->
- gen_server:call(Server, next_changes, infinity).
+ try gen_server:call(Server, next_changes, 31000)
+ catch exit:{timeout, _Reason} -> throw(changes_timeout)
+ end.
stop(Server) ->
gen_server:call(Server, stop).
@@ -83,8 +85,7 @@
resource = "_changes",
qs = QS,
conn = Pid,
- options = [{stream_to, {self(), once}}, {response_format, binary},
- {inactivity_timeout, 31000}], % miss 3 heartbeats, assume death
+ options = [{stream_to, {self(), once}}, {response_format, binary}],
headers = Source#http_db.headers -- [{"Accept-Encoding", "gzip"}]
},
{ibrowse_req_id, ReqId} = couch_rep_httpc:request(Req),
@@ -202,6 +203,9 @@
?LOG_ERROR("changes_loop died with reason ~p", [Reason]),
{stop, changes_loop_died, State};
+handle_info({'EXIT', _From, normal}, State) ->
+ {noreply, State};
+
handle_info(Msg, State) ->
?LOG_DEBUG("unexpected message at changes_feed ~p", [Msg]),
{noreply, State}.