summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--share/www/script/test/changes.js39
-rw-r--r--src/couchdb/couch_httpd_db.erl36
2 files changed, 58 insertions, 17 deletions
diff --git a/share/www/script/test/changes.js b/share/www/script/test/changes.js
index d805d6cd..1800ca82 100644
--- a/share/www/script/test/changes.js
+++ b/share/www/script/test/changes.js
@@ -44,7 +44,7 @@ couchTests.changes = function(debug) {
T(jsonp_flag == 1);
- req = CouchDB.request("GET", "/test_suite_db/_changes?continuous=true&timeout=10");
+ req = CouchDB.request("GET", "/test_suite_db/_changes?feed=continuous&timeout=10");
var resp = JSON.parse(req.responseText);
T(resp.results.length == 1 && resp.last_seq==1)
T(resp.results[0].changes[0].rev == docFoo._rev)
@@ -75,7 +75,7 @@ couchTests.changes = function(debug) {
}
- xhr.open("GET", "/test_suite_db/_changes?continuous=true", true);
+ xhr.open("GET", "/test_suite_db/_changes?feed=continuous", true);
xhr.send("");
var docBar = {_id:"bar", bar:1};
@@ -113,7 +113,7 @@ couchTests.changes = function(debug) {
xhr = CouchDB.newXhr();
//verify the hearbeat newlines are sent
- xhr.open("GET", "/test_suite_db/_changes?continuous=true&heartbeat=10", true);
+ xhr.open("GET", "/test_suite_db/_changes?feed=continuous&heartbeat=10", true);
xhr.send("");
sleep(100);
@@ -122,6 +122,39 @@ couchTests.changes = function(debug) {
T(str.charAt(str.length - 1) == "\n")
T(str.charAt(str.length - 2) == "\n")
+
+
+ // test longpolling
+ xhr = CouchDB.newXhr();
+
+ xhr.open("GET", "/test_suite_db/_changes?feed=longpoll", true);
+ xhr.send("");
+
+ sleep(100);
+ var lines = xhr.responseText.split("\n");
+ T(lines[5]=='"last_seq":3}');
+
+ xhr = CouchDB.newXhr();
+
+ xhr.open("GET", "/test_suite_db/_changes?feed=longpoll&since=3", true);
+ xhr.send("");
+
+ sleep(100);
+
+ var docBarz = {_id:"barz", bar:1};
+ db.save(docBarz);
+
+ sleep(100);
+
+ var lines = xhr.responseText.split("\n");
+
+ change = parse_changes_line(lines[1]);
+
+ T(change.seq == 4);
+ T(change.id == "barz");
+ T(change.changes[0].rev == docBarz._rev);
+ T(lines[3]=='"last_seq":4}');
+
}
// test the filtered changes
diff --git a/src/couchdb/couch_httpd_db.erl b/src/couchdb/couch_httpd_db.erl
index 7498a521..63ae5563 100644
--- a/src/couchdb/couch_httpd_db.erl
+++ b/src/couchdb/couch_httpd_db.erl
@@ -64,12 +64,13 @@ get_changes_timeout(Req, Resp) ->
fun() -> send_chunk(Resp, "\n"), ok end}
end.
+
handle_changes_req(#httpd{method='GET',path_parts=[DbName|_]}=Req, Db) ->
StartSeq = list_to_integer(couch_httpd:qs_value(Req, "since", "0")),
{ok, Resp} = start_json_response(Req, 200),
send_chunk(Resp, "{\"results\":[\n"),
- case couch_httpd:qs_value(Req, "continuous", "false") of
- "true" ->
+ case couch_httpd:qs_value(Req, "feed", "normal") of
+ ResponseType when ResponseType == "continuous" orelse ResponseType == "longpoll"->
Self = self(),
{ok, Notify} = couch_db_update_notifier:start_link(
fun({_, DbName0}) when DbName0 == DbName ->
@@ -81,16 +82,15 @@ handle_changes_req(#httpd{method='GET',path_parts=[DbName|_]}=Req, Db) ->
couch_stats_collector:track_process_count(Self,
{httpd, clients_requesting_changes}),
try
- keep_sending_changes(Req, Resp, Db, StartSeq, <<"">>, Timeout, TimeoutFun)
+ keep_sending_changes(Req, Resp, Db, StartSeq, <<"">>, Timeout, TimeoutFun, ResponseType)
after
couch_db_update_notifier:stop(Notify),
get_rest_db_updated() % clean out any remaining update messages
end;
- "false" ->
+ "normal" ->
{ok, {LastSeq, _Prepend}} =
send_changes(Req, Resp, Db, StartSeq, <<"">>),
- send_chunk(Resp, io_lib:format("\n],\n\"last_seq\":~w}\n", [LastSeq])),
- end_json_response(Resp)
+ end_sending_changes(Resp, LastSeq)
end;
handle_changes_req(#httpd{path_parts=[_,<<"_changes">>]}=Req, _Db) ->
@@ -110,17 +110,25 @@ get_rest_db_updated() ->
receive db_updated -> get_rest_db_updated()
after 0 -> updated
end.
+
+end_sending_changes(Resp, EndSeq) ->
+ send_chunk(Resp, io_lib:format("\n],\n\"last_seq\":~w}\n", [EndSeq])),
+ end_json_response(Resp).
-keep_sending_changes(#httpd{user_ctx=UserCtx,path_parts=[DbName|_]}=Req, Resp, Db, StartSeq, Prepend, Timeout, TimeoutFun) ->
+keep_sending_changes(#httpd{user_ctx=UserCtx,path_parts=[DbName|_]}=Req, Resp, Db, StartSeq, Prepend, Timeout, TimeoutFun, ResponseType) ->
{ok, {EndSeq, Prepend2}} = send_changes(Req, Resp, Db, StartSeq, Prepend),
couch_db:close(Db),
- case wait_db_updated(Timeout, TimeoutFun) of
- updated ->
- {ok, Db2} = couch_db:open(DbName, [{user_ctx, UserCtx}]),
- keep_sending_changes(Req, Resp, Db2, EndSeq, Prepend2, Timeout, TimeoutFun);
- stop ->
- send_chunk(Resp, io_lib:format("\n],\n\"last_seq\":~w}\n", [EndSeq])),
- end_json_response(Resp)
+ if
+ EndSeq > StartSeq, ResponseType == "longpoll" ->
+ end_sending_changes(Resp, EndSeq);
+ true ->
+ case wait_db_updated(Timeout, TimeoutFun) of
+ updated ->
+ {ok, Db2} = couch_db:open(DbName, [{user_ctx, UserCtx}]),
+ keep_sending_changes(Req, Resp, Db2, EndSeq, Prepend2, Timeout, TimeoutFun, ResponseType);
+ stop ->
+ end_sending_changes(Resp, EndSeq)
+ end
end.
send_changes(Req, Resp, Db, StartSeq, Prepend0) ->