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:22:49 +0000
commitab01683993a8247ceaadb2f464885a86d85d953f (patch)
tree3bd0ef84580c67e73891378cd86589cf31c7ae39
parent32dba5863edba786309bd1757906937f13006d14 (diff)
downloadcouchdb-changes_filter_all_docs_oom_main.tar.gz
Retry filter_docs sequentially if the patch exceeds couchjs stackchanges_filter_all_docs_oom_main
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]).