Oh, I missed the scoping a bit on that. Should be for browsers, but for the CLI tests I wouldn't be surprised if that fails with a "no property named EventSource on undefined" or whatever. I'd just add a if(window && window.EventSource) to fix if that's the case.
Though we should add a ticket to revisit this since we're theoretically moving to the CLI tests, no point having test code that never runs and all that. On Wed, May 16, 2012 at 12:44 AM, Benoit Chesneau <[email protected]> wrote: > On Wed, May 16, 2012 at 7:42 AM, Paul Davis <[email protected]> > wrote: >> That JS test looks broken for JS environments that don't support >> EventSource. Notably the CLI test suite but also browsers that don't >> implement it. I'd either move the entire test into the conditional or >> reimplement it by parsing the actual data sent across. >> > > > well there is an if() . Isn't it enough ? > > - benoit >> On Wed, May 16, 2012 at 12:36 AM, <[email protected]> wrote: >>> Updated Branches: >>> refs/heads/master af7441d8d -> 093d2aa65 >>> >>> >>> add Server-Sent Events protocol to db changes API. close #COUCHDB-986 >>> >>> This patch add support for the new specification of w3c by adding a new >>> feed type named `eventsource`: >>> >>> http://www.w3.org/TR/2009/WD-eventsource-20090423/ >>> >>> This patch is based on @indutny patch with edits. >>> >>> >>> Project: http://git-wip-us.apache.org/repos/asf/couchdb/repo >>> Commit: http://git-wip-us.apache.org/repos/asf/couchdb/commit/093d2aa6 >>> Tree: http://git-wip-us.apache.org/repos/asf/couchdb/tree/093d2aa6 >>> Diff: http://git-wip-us.apache.org/repos/asf/couchdb/diff/093d2aa6 >>> >>> Branch: refs/heads/master >>> Commit: 093d2aa6544546a95f6133f1db3c4f4179793f3c >>> Parents: af7441d >>> Author: benoitc <[email protected]> >>> Authored: Wed May 16 07:30:19 2012 +0200 >>> Committer: benoitc <[email protected]> >>> Committed: Wed May 16 07:30:19 2012 +0200 >>> >>> ---------------------------------------------------------------------- >>> share/www/script/test/changes.js | 28 ++++++++++++++++++++++++++++ >>> src/couchdb/couch_changes.erl | 15 ++++++++++----- >>> src/couchdb/couch_httpd_db.erl | 24 ++++++++++++++++++++++-- >>> 3 files changed, 60 insertions(+), 7 deletions(-) >>> ---------------------------------------------------------------------- >>> >>> >>> http://git-wip-us.apache.org/repos/asf/couchdb/blob/093d2aa6/share/www/script/test/changes.js >>> ---------------------------------------------------------------------- >>> diff --git a/share/www/script/test/changes.js >>> b/share/www/script/test/changes.js >>> index 19e22fd..c529b21 100644 >>> --- a/share/www/script/test/changes.js >>> +++ b/share/www/script/test/changes.js >>> @@ -139,6 +139,34 @@ couchTests.changes = function(debug) { >>> // otherwise we'll continue to receive heartbeats forever >>> xhr.abort(); >>> >>> + // test Server Sent Event (eventsource) >>> + if (window.EventSource) { >>> + var source = new EventSource( >>> + "/test_suite_db/_changes?feed=eventsource"); >>> + var results = []; >>> + var sourceListener = function(e) { >>> + var data = JSON.parse(e.data); >>> + results.push(data); >>> + >>> + }; >>> + >>> + source.addEventListener('message', sourceListener , false); >>> + >>> + waitForSuccess(function() { >>> + if (results.length != 3) >>> + throw "bad seq, try again"; >>> + }); >>> + >>> + source.removeEventListener('message', sourceListener, false); >>> + >>> + T(results[0].seq == 1); >>> + T(results[0].id == "foo"); >>> + >>> + T(results[1].seq == 2); >>> + T(results[1].id == "bar"); >>> + T(results[1].changes[0].rev == docBar._rev); >>> + } >>> + >>> // test longpolling >>> xhr = CouchDB.newXhr(); >>> >>> >>> http://git-wip-us.apache.org/repos/asf/couchdb/blob/093d2aa6/src/couchdb/couch_changes.erl >>> ---------------------------------------------------------------------- >>> diff --git a/src/couchdb/couch_changes.erl b/src/couchdb/couch_changes.erl >>> index aec7873..85c9e54 100644 >>> --- a/src/couchdb/couch_changes.erl >>> +++ b/src/couchdb/couch_changes.erl >>> @@ -63,7 +63,8 @@ handle_changes(Args1, Req, Db0) -> >>> put(last_changes_heartbeat, now()) >>> end, >>> >>> - if Feed == "continuous" orelse Feed == "longpoll" -> >>> + case lists:member(Feed, ["continuous", "longpoll", "eventsource"]) of >>> + true -> >>> fun(CallbackAcc) -> >>> {Callback, UserAcc} = get_callback_acc(CallbackAcc), >>> Self = self(), >>> @@ -89,7 +90,7 @@ handle_changes(Args1, Req, Db0) -> >>> get_rest_db_updated(ok) % clean out any remaining update >>> messages >>> end >>> end; >>> - true -> >>> + false -> >>> fun(CallbackAcc) -> >>> {Callback, UserAcc} = get_callback_acc(CallbackAcc), >>> UserAcc2 = start_sending_changes(Callback, UserAcc, Feed), >>> @@ -261,7 +262,9 @@ get_changes_timeout(Args, Callback) -> >>> fun(UserAcc) -> {ok, Callback(timeout, ResponseType, UserAcc)} >>> end} >>> end. >>> >>> -start_sending_changes(_Callback, UserAcc, "continuous") -> >>> +start_sending_changes(_Callback, UserAcc, ResponseType) >>> + when ResponseType =:= "continuous" >>> + orelse ResponseType =:= "eventsource" -> >>> UserAcc; >>> start_sending_changes(Callback, UserAcc, ResponseType) -> >>> Callback(start, ResponseType, UserAcc). >>> @@ -434,7 +437,9 @@ keep_sending_changes(Args, Acc0, FirstRound) -> >>> end_sending_changes(Callback, UserAcc, EndSeq, ResponseType) -> >>> Callback({stop, EndSeq}, ResponseType, UserAcc). >>> >>> -changes_enumerator(DocInfo, #changes_acc{resp_type = "continuous"} = Acc) >>> -> >>> +changes_enumerator(DocInfo, #changes_acc{resp_type = ResponseType} = Acc) >>> + when ResponseType =:= "continuous" >>> + orelse ResponseType =:= "eventsource" -> >>> #changes_acc{ >>> filter = FilterFun, callback = Callback, >>> user_acc = UserAcc, limit = Limit, db = Db, >>> @@ -456,7 +461,7 @@ changes_enumerator(DocInfo, #changes_acc{resp_type = >>> "continuous"} = Acc) -> >>> end; >>> _ -> >>> ChangesRow = changes_row(Results, DocInfo, Acc), >>> - UserAcc2 = Callback({change, ChangesRow, <<>>}, "continuous", >>> UserAcc), >>> + UserAcc2 = Callback({change, ChangesRow, <<>>}, ResponseType, >>> UserAcc), >>> reset_heartbeat(), >>> {Go, Acc#changes_acc{seq = Seq, user_acc = UserAcc2, limit = Limit >>> - 1}} >>> end; >>> >>> http://git-wip-us.apache.org/repos/asf/couchdb/blob/093d2aa6/src/couchdb/couch_httpd_db.erl >>> ---------------------------------------------------------------------- >>> diff --git a/src/couchdb/couch_httpd_db.erl b/src/couchdb/couch_httpd_db.erl >>> index de39b9e..0920014 100644 >>> --- a/src/couchdb/couch_httpd_db.erl >>> +++ b/src/couchdb/couch_httpd_db.erl >>> @@ -76,14 +76,23 @@ handle_changes_req1(Req, #db{name=DbName}=Db) -> >>> >>> handle_changes_req2(Req, Db) -> >>> MakeCallback = fun(Resp) -> >>> - fun({change, Change, _}, "continuous") -> >>> + fun({change, {ChangeProp}=Change, _}, "eventsource") -> >>> + Seq = proplists:get_value(<<"seq">>, ChangeProp), >>> + send_chunk(Resp, ["data: ", ?JSON_ENCODE(Change), >>> + "\n", "id: ", ?JSON_ENCODE(Seq), >>> + "\n\n"]); >>> + ({change, Change, _}, "continuous") -> >>> send_chunk(Resp, [?JSON_ENCODE(Change) | "\n"]); >>> ({change, Change, Prepend}, _) -> >>> send_chunk(Resp, [Prepend, ?JSON_ENCODE(Change)]); >>> + (start, "eventsource") -> >>> + ok; >>> (start, "continuous") -> >>> ok; >>> (start, _) -> >>> send_chunk(Resp, "{\"results\":[\n"); >>> + ({stop, _EndSeq}, "eventsource") -> >>> + end_json_response(Resp); >>> ({stop, EndSeq}, "continuous") -> >>> send_chunk( >>> Resp, >>> @@ -118,6 +127,15 @@ handle_changes_req2(Req, Db) -> >>> end >>> ) >>> end; >>> + "eventsource" -> >>> + Headers = [ >>> + {"Content-Type", "text/event-stream"}, >>> + {"Cache-Control", "no-cache"} >>> + ], >>> + {ok, Resp} = couch_httpd:start_json_response(Req, 200, Headers), >>> + fun(FeedChangesFun) -> >>> + FeedChangesFun(MakeCallback(Resp)) >>> + end; >>> _ -> >>> % "longpoll" or "continuous" >>> {ok, Resp} = couch_httpd:start_json_response(Req, 200), >>> @@ -1097,13 +1115,15 @@ parse_doc_query(Req) -> >>> >>> parse_changes_query(Req) -> >>> lists:foldl(fun({Key, Value}, Args) -> >>> - case {Key, Value} of >>> + case {string:to_lower(Key), Value} of >>> {"feed", _} -> >>> Args#changes_args{feed=Value}; >>> {"descending", "true"} -> >>> Args#changes_args{dir=rev}; >>> {"since", _} -> >>> Args#changes_args{since=list_to_integer(Value)}; >>> + {"last-event-id", _} -> >>> + Args#changes_args{since=list_to_integer(Value)}; >>> {"limit", _} -> >>> Args#changes_args{limit=list_to_integer(Value)}; >>> {"style", _} -> >>>
