From 0678742e4d0176807b221fb519c211a579c4baf2 Mon Sep 17 00:00:00 2001 From: Robert Newson Date: Thu, 5 Nov 2020 17:20:12 +0000 Subject: 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 --- src/couch/src/couch_query_servers.erl | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) 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]). -- cgit v1.2.1