summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Newson <rnewson@apache.org>2020-11-05 17:20:12 +0000
committerRobert Newson <rnewson@apache.org>2020-11-06 15:58:41 +0000
commita499d6f2313bb3a5dd355e1a5a3353856ac7e791 (patch)
tree97d4b4bb513dabdaeb4d0fd61fdc3d1bfdf2aed6
parent4b107505e9862af35fe616e12892fdf6cfffb12d (diff)
downloadcouchdb-a499d6f2313bb3a5dd355e1a5a3353856ac7e791.tar.gz
Retry filter_docs sequentially if the patch exceeds couchjs stack
A document with lots of conflicts can blow up couchjs if the user calls _changes with a javascript filter and with `style=all_docs` as this option causes up to fetch all the conflicts. All leaf revisions of the document are then passed in a single call to ddoc_prompt, which can fail if there's a lot of them. In that event, we simply try them sequentially and assemble the response from each call. Should be backported to 3.x
-rw-r--r--src/couch/src/couch_query_servers.erl14
1 files changed, 13 insertions, 1 deletions
diff --git a/src/couch/src/couch_query_servers.erl b/src/couch/src/couch_query_servers.erl
index 8eb07abbf..5cafcb002 100644
--- a/src/couch/src/couch_query_servers.erl
+++ b/src/couch/src/couch_query_servers.erl
@@ -500,9 +500,21 @@ filter_docs(Req, Db, DDoc, FName, Docs) ->
end,
Options = json_doc_options(),
JsonDocs = [json_doc(Doc, Options) || Doc <- Docs],
+ try
+ {ok, filter_docs_int(DDoc, FName, JsonReq, JsonDocs)}
+ catch
+ throw:{os_process_error,{exit_status,1}} ->
+ %% batch used too much memory, retry sequentially.
+ Fun = fun(JsonDoc) ->
+ filter_docs_int(DDoc, FName, JsonReq, [JsonDoc])
+ end,
+ {ok, lists:flatmap(Fun, JsonDocs)}
+ end.
+
+filter_docs_int(DDoc, FName, JsonReq, JsonDocs) ->
[true, Passes] = ddoc_prompt(DDoc, [<<"filters">>, FName],
[JsonDocs, JsonReq]),
- {ok, Passes}.
+ Passes.
ddoc_proc_prompt({Proc, DDocId}, FunPath, Args) ->
proc_prompt(Proc, [<<"ddoc">>, DDocId, FunPath, Args]).