Send a real EventSource event for heartbeat
The EventSource connection can get stuck (in TCP half-open state*) and there's
no way
for the client to detect that. This commit changes the way heartbeat is sent,
instead of
sending a newline character, it sends an empty event of type heartbeat:
event: heartbeat
data:
This event doesn't have an id: field, so the client will retain its latest
Last-Event-ID state.
This doesn't change the expectations of clients that used EventSource till now,
because they
subscribe to the 'message' event type. To get the 'heartbeat' events a client
will need to
explicitly subscribe to it:
source.addEventListener('heartbeat', function () { /* cancel a timer that
would otherwise reconnect the source */ });
* this can happen when you suspend your laptop, on flaky internet connection,
ADSL reconnect,
bad wifi signals, bad routers etc. Pretty often in a typical internet usage
nowadays.
Project: http://git-wip-us.apache.org/repos/asf/couchdb/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb/commit/95600b70
Tree: http://git-wip-us.apache.org/repos/asf/couchdb/tree/95600b70
Diff: http://git-wip-us.apache.org/repos/asf/couchdb/diff/95600b70
Branch: refs/heads/1.6.x
Commit: 95600b70e6cd36e460cc06958f624954419aa9e1
Parents: 7fe8509
Author: Damjan Georgievski <[email protected]>
Authored: Fri May 2 17:04:41 2014 +0200
Committer: Klaus Trainer <[email protected]>
Committed: Tue May 13 14:53:42 2014 +0200
----------------------------------------------------------------------
share/doc/src/api/database/changes.rst | 10 ++++++++++
share/www/script/test/changes.js | 21 ++++++++++++++++++++-
src/couchdb/couch_httpd_db.erl | 2 ++
3 files changed, 32 insertions(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/couchdb/blob/95600b70/share/doc/src/api/database/changes.rst
----------------------------------------------------------------------
diff --git a/share/doc/src/api/database/changes.rst
b/share/doc/src/api/database/changes.rst
index fc46412..6e48f9b 100644
--- a/share/doc/src/api/database/changes.rst
+++ b/share/doc/src/api/database/changes.rst
@@ -398,6 +398,16 @@ parameter.
}
+If you set a heartbeat interval (using the ``heartbeat`` query argument),
CouchDB will
+send a ``hearbeat`` event that you can subscribe to with:
+
+.. code-block:: javascript
+
+ source.addEventListener('heartbeat', function () {}, false);
+
+This can be monitored by the client application to restart the EventSource
connection if
+needed (i.e. if the TCP connection gets stuck in a half-open state).
+
.. note::
EventSource connections are subject to cross-origin resource sharing
http://git-wip-us.apache.org/repos/asf/couchdb/blob/95600b70/share/www/script/test/changes.js
----------------------------------------------------------------------
diff --git a/share/www/script/test/changes.js b/share/www/script/test/changes.js
index 0fba9f9..b034a0b 100644
--- a/share/www/script/test/changes.js
+++ b/share/www/script/test/changes.js
@@ -123,7 +123,7 @@ couchTests.changes = function(debug) {
xhr = CouchDB.newXhr();
- //verify the hearbeat newlines are sent
+ //verify the heartbeat newlines are sent
xhr.open("GET",
CouchDB.proxyUrl("/test_suite_db/_changes?feed=continuous&heartbeat=10&timeout=500"),
true);
xhr.send("");
@@ -171,6 +171,25 @@ couchTests.changes = function(debug) {
T(results[1].changes[0].rev == docBar._rev);
}
+ // test that we receive EventSource heartbeat events
+ if (!!window.EventSource) {
+ var source = new EventSource(
+ "/test_suite_db/_changes?feed=eventsource&heartbeat=10");
+
+ var count_heartbeats = 0;
+ source.addEventListener('heartbeat', function () { count_heartbeats =
count_heartbeats + 1; } , false);
+
+ waitForSuccess(function() {
+ if (count_heartbeats < 3) {
+ throw "keep waiting";
+ }
+ return true;
+ }, "eventsource-heartbeat");
+
+ T(count_heartbeats >= 3);
+ source.close();
+ }
+
// test longpolling
xhr = CouchDB.newXhr();
http://git-wip-us.apache.org/repos/asf/couchdb/blob/95600b70/src/couchdb/couch_httpd_db.erl
----------------------------------------------------------------------
diff --git a/src/couchdb/couch_httpd_db.erl b/src/couchdb/couch_httpd_db.erl
index 6940e47..c52094e 100644
--- a/src/couchdb/couch_httpd_db.erl
+++ b/src/couchdb/couch_httpd_db.erl
@@ -105,6 +105,8 @@ handle_changes_req2(Req, Db) ->
io_lib:format("\n],\n\"last_seq\":~w}\n", [EndSeq])
),
end_json_response(Resp);
+ (timeout, "eventsource") ->
+ send_chunk(Resp, "event: heartbeat\ndata: \n\n");
(timeout, _) ->
send_chunk(Resp, "\n")
end