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-05 17:43:52 +0000
commit0678742e4d0176807b221fb519c211a579c4baf2 (patch)
tree4dad6620980693a493678d2cab27c6e1058301c9
parent077b09cb21dc8dbb6d52d8d81b2afc33bca835fe (diff)
downloadcouchdb-0678742e4d0176807b221fb519c211a579c4baf2.tar.gz
Retry filter_docs sequentially if the patch exceeds couchjs stackchanges_filter_all_docs_oom_3.x
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 447daea61..6649df364 100644
--- a/src/couch/src/couch_query_servers.erl
+++ b/src/couch/src/couch_query_servers.erl
@@ -495,9 +495,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]).