summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul J. Davis <paul.joseph.davis@gmail.com>2017-09-07 14:37:36 -0500
committerJan Lehnardt <jan@apache.org>2017-10-09 21:41:58 +0200
commitb030a8648214d88411191dd74f65ee4edc0ed7a2 (patch)
treef60180d6dd62815cc98376dcf0feee63ea4a62a8
parentc26ce7f4093de17d4d57edde622f2a34c6ba2b07 (diff)
downloadcouchdb-improve-reduce-limit-errors.tar.gz
Return reduce overflow errors to the clientimprove-reduce-limit-errors
This changes the reduce overflow error to return an error to the client rather than blowing up the view build. This allows views that have a single bad reduce to build while not crushing the server's RAM usage.
-rw-r--r--src/couch/src/couch_query_servers.erl29
-rw-r--r--src/couch_mrview/src/couch_mrview_http.erl6
-rw-r--r--src/fabric/src/fabric_util.erl2
-rw-r--r--src/fabric/src/fabric_view.erl2
-rw-r--r--test/javascript/tests/view_errors.js4
5 files changed, 33 insertions, 10 deletions
diff --git a/src/couch/src/couch_query_servers.erl b/src/couch/src/couch_query_servers.erl
index 63b0e3900..4928eea32 100644
--- a/src/couch/src/couch_query_servers.erl
+++ b/src/couch/src/couch_query_servers.erl
@@ -125,20 +125,39 @@ os_reduce(Lang, OsRedSrcs, KVs) ->
Proc = get_os_process(Lang),
OsResults = try proc_prompt(Proc, [<<"reduce">>, OsRedSrcs, KVs]) of
[true, Reductions] -> Reductions
+ catch
+ throw:{reduce_overflow_error, Msg} ->
+ [{[{reduce_overflow_error, Msg}]} || _ <- OsRedSrcs]
after
ok = ret_os_process(Proc)
end,
{ok, OsResults}.
os_rereduce(Lang, OsRedSrcs, KVs) ->
- Proc = get_os_process(Lang),
- try proc_prompt(Proc, [<<"rereduce">>, OsRedSrcs, KVs]) of
- [true, [Reduction]] -> Reduction
- after
- ok = ret_os_process(Proc)
+ case get_overflow_error(KVs) of
+ undefined ->
+ Proc = get_os_process(Lang),
+ try proc_prompt(Proc, [<<"rereduce">>, OsRedSrcs, KVs]) of
+ [true, [Reduction]] -> Reduction
+ catch
+ throw:{reduce_overflow_error, Msg} ->
+ {[{reduce_overflow_error, Msg}]}
+ after
+ ok = ret_os_process(Proc)
+ end;
+ Error ->
+ Error
end.
+get_overflow_error([]) ->
+ undefined;
+get_overflow_error([{[{reduce_overflow_error, _}]} = Error | _]) ->
+ Error;
+get_overflow_error([_ | Rest]) ->
+ get_overflow_error(Rest).
+
+
builtin_reduce(_Re, [], _KVs, Acc) ->
{ok, lists:reverse(Acc)};
builtin_reduce(Re, [<<"_sum",_/binary>>|BuiltinReds], KVs, Acc) ->
diff --git a/src/couch_mrview/src/couch_mrview_http.erl b/src/couch_mrview/src/couch_mrview_http.erl
index 9ad50eeef..004caef09 100644
--- a/src/couch_mrview/src/couch_mrview_http.erl
+++ b/src/couch_mrview/src/couch_mrview_http.erl
@@ -440,7 +440,11 @@ row_to_json(error, Row) ->
% match prior behavior.
Key = couch_util:get_value(key, Row),
Val = couch_util:get_value(value, Row),
- Obj = {[{key, Key}, {error, Val}]},
+ Reason = couch_util:get_value(reason, Row),
+ ReasonProp = if Reason == undefined -> []; true ->
+ [{reason, Reason}]
+ end,
+ Obj = {[{key, Key}, {error, Val}] ++ ReasonProp},
?JSON_ENCODE(Obj);
row_to_json(Id0, Row) ->
Id = case Id0 of
diff --git a/src/fabric/src/fabric_util.erl b/src/fabric/src/fabric_util.erl
index bf3f023db..49f4c8913 100644
--- a/src/fabric/src/fabric_util.erl
+++ b/src/fabric/src/fabric_util.erl
@@ -203,8 +203,6 @@ get_shard([#shard{node = Node, name = Name} | Rest], Opts, Timeout, Factor) ->
rexi_monitor:stop(Mon)
end.
-error_info({{<<"reduce_overflow_error">>, _} = Error, _Stack}) ->
- Error;
error_info({{timeout, _} = Error, _Stack}) ->
Error;
error_info({{Error, Reason}, Stack}) ->
diff --git a/src/fabric/src/fabric_view.erl b/src/fabric/src/fabric_view.erl
index 45262e4eb..dd0fcfd8b 100644
--- a/src/fabric/src/fabric_view.erl
+++ b/src/fabric/src/fabric_view.erl
@@ -258,6 +258,8 @@ find_next_key([], _, _, _) ->
find_next_key([Key|Rest], _, _, _) ->
{Key, Rest}.
+transform_row(#view_row{value={[{reduce_overflow_error, Msg}]}}) ->
+ {row, [{key,null}, {id,error}, {value,reduce_overflow_error}, {reason,Msg}]};
transform_row(#view_row{key=Key, id=reduced, value=Value}) ->
{row, [{key,Key}, {value,Value}]};
transform_row(#view_row{key=Key, id=undefined}) ->
diff --git a/test/javascript/tests/view_errors.js b/test/javascript/tests/view_errors.js
index b53a3c764..0d9cd79fb 100644
--- a/test/javascript/tests/view_errors.js
+++ b/test/javascript/tests/view_errors.js
@@ -174,9 +174,9 @@ couchTests.view_errors = function(debug) {
// if the reduce grows to fast, throw an overflow error
var path = "/" + db_name + "/_design/testbig/_view/reduce_too_big";
xhr = CouchDB.request("GET", path);
- T(xhr.status == 500);
+ T(xhr.status == 200);
result = JSON.parse(xhr.responseText);
- T(result.error == "reduce_overflow_error");
+ T(result.rows[0].error == "reduce_overflow_error");
try {
db.query(function() {emit(null, null)}, null, {startkey: 2, endkey:1});