Repository: couchdb-couch-mrview Updated Branches: refs/heads/3060-handle-multi-query 872227103 -> 93269c1cc (forced update)
Properly handle multi-query streaming of results After commit: https://github.com/apache/couchdb-couch-mrview/commit/3ce28641c85af0d5054df47e9ac7de917a9d33cd In `view_cb` if row came before meta, `row_sent` flag was set to not send meta later. That makes sense for a single query. However, in case of multiple queries, which could produce this sequence of callbacks: meta , row, ... , complete, meta, row, ..., complete Second query meta won't be sent because row_sent flag remains true. So to fix, make sure to reset row_sent=false in after each `complete`. Also introduce a `meta_sent` flag, to cover the case when meta was sent for second request and on first row we don't want to sent `{"rows":[...`. Jira: COUCHDB-3060 Project: http://git-wip-us.apache.org/repos/asf/couchdb-couch-mrview/repo Commit: http://git-wip-us.apache.org/repos/asf/couchdb-couch-mrview/commit/93269c1c Tree: http://git-wip-us.apache.org/repos/asf/couchdb-couch-mrview/tree/93269c1c Diff: http://git-wip-us.apache.org/repos/asf/couchdb-couch-mrview/diff/93269c1c Branch: refs/heads/3060-handle-multi-query Commit: 93269c1cc6e83c2d14aa17e10a4b8d08fb9a3beb Parents: 157132c Author: Nick Vatamaniuc <[email protected]> Authored: Wed Aug 24 23:17:00 2016 -0400 Committer: Nick Vatamaniuc <[email protected]> Committed: Thu Aug 25 10:02:09 2016 -0400 ---------------------------------------------------------------------- include/couch_mrview.hrl | 3 ++- src/couch_mrview_http.erl | 15 ++++++++++----- 2 files changed, 12 insertions(+), 6 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/couchdb-couch-mrview/blob/93269c1c/include/couch_mrview.hrl ---------------------------------------------------------------------- diff --git a/include/couch_mrview.hrl b/include/couch_mrview.hrl index 2dfd398..bfd20ad 100644 --- a/include/couch_mrview.hrl +++ b/include/couch_mrview.hrl @@ -99,7 +99,8 @@ buffer = [], bufsize = 0, threshold = 1490, - row_sent = false + row_sent = false, + meta_sent = false }). -record(lacc, { http://git-wip-us.apache.org/repos/asf/couchdb-couch-mrview/blob/93269c1c/src/couch_mrview_http.erl ---------------------------------------------------------------------- diff --git a/src/couch_mrview_http.erl b/src/couch_mrview_http.erl index 3a9aa33..b5e6d00 100644 --- a/src/couch_mrview_http.erl +++ b/src/couch_mrview_http.erl @@ -360,12 +360,16 @@ view_cb({meta, Meta}, #vacc{}=Acc) -> end ++ ["\"rows\":["], Chunk = [prepend_val(Acc), "{", string:join(Parts, ","), "\r\n"], {ok, AccOut} = maybe_flush_response(Acc, Chunk, iolist_size(Chunk)), - {ok, AccOut#vacc{prepend=""}}; + {ok, AccOut#vacc{prepend="", meta_sent=true}}; view_cb({row, Row}, #vacc{resp=undefined}=Acc) -> % sorted=false and a row arrived before meta, start response. Pre = "{\"rows\":[\r\n", {ok, Resp} = chttpd:start_delayed_json_response(Acc#vacc.req, 200, []), view_cb({row, Row}, Acc#vacc{row_sent=true,resp=Resp, prepend=Pre, should_close=true}); +view_cb({row, Row}, #vacc{row_sent=false, meta_sent=false}=Acc) -> + % sorted=false and a row arrived before meta, emit a no-meta "rows:" header + Pre = prepend_val(Acc) ++ "{\"rows\":[\r\n", + view_cb({row, Row}, Acc#vacc{row_sent=true, prepend=Pre}); view_cb({row, Row}, Acc) -> % Adding another row Chunk = [prepend_val(Acc), row_to_json(Row)], @@ -373,16 +377,17 @@ view_cb({row, Row}, Acc) -> view_cb(complete, #vacc{resp=undefined}=Acc) -> % Nothing in view {ok, Resp} = chttpd:send_json(Acc#vacc.req, 200, {[{rows, []}]}), - {ok, Acc#vacc{resp=Resp}}; + {ok, Acc#vacc{resp=Resp, row_sent=false, meta_sent=false}}; view_cb(complete, #vacc{resp=Resp, buffer=Buf, threshold=Max}=Acc) -> % Finish view output and possibly end the response {ok, Resp1} = chttpd:close_delayed_json_object(Resp, Buf, "\r\n]}", Max), - case Acc#vacc.should_close of + Acc1 = Acc#vacc{row_sent=false, meta_sent=false}, + case Acc1#vacc.should_close of true -> {ok, Resp2} = chttpd:end_delayed_json_response(Resp1), - {ok, Acc#vacc{resp=Resp2}}; + {ok, Acc1#vacc{resp=Resp2}}; _ -> - {ok, Acc#vacc{resp=Resp1, prepend=",\r\n", buffer=[], bufsize=0}} + {ok, Acc1#vacc{resp=Resp1, prepend=",\r\n", buffer=[], bufsize=0}} end; view_cb({error, Reason}, #vacc{resp=undefined}=Acc) -> {ok, Resp} = chttpd:send_error(Acc#vacc.req, Reason),
