couchdb-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From j..@apache.org
Subject git commit: Import couch_dbupdates from rcouch.
Date Mon, 04 Mar 2013 13:28:15 GMT
Updated Branches:
  refs/heads/1684-feature-db-updates [created] 15c31508b


Import couch_dbupdates from rcouch.

This creates a new top level API endpoint: `/_db_updates`
that returns a line of JSON for each database event along
with the database name.

A database event is one of `created`, `updated`, `deleted`.

The API endpoint supports a `?feed=` parameter with the
options: `longpoll`, `continuous` and `eventsource`.

A second parameter `timeout=` specifies when the server should
close the connection.

`longpoll` closes the connection after a single notification.
It is the default option.

`continuous` keeps a socket open until the specified `timeout`
or 60 seconds by default.

`eventsource` works like continuous, but sends the data in
EventSource format. See http://dev.w3.org/html5/eventsource/

The parameters are modelled after the existing `/_changes` API
endpoint. Note that `/_db_updates` does not support resuming
of notifications via a sequence ID.

This is a port of the existing DbUpdateNotification interface
to the HTTP API.

Functional changes compared to rcouch:

 - make _db_updates an admin-only resource

Docs:

 - updated api/misc to include basic info on `/_db_updates`

License:

  Apache 2 license, updated LICENSE.

Notice:

  (c) 2012 Benoit Chesneau, updated NOTICE.

Tests:

 - only manual testing of the various API differences due to
   complications with asynchronous HTTP requests in the JS
   test suite and total annoyance of overly complicated
   ibrowse/httpc modules for writing etap tests.

Recommendation to ship this as EXPERIMENTAL until we have tests.


Project: http://git-wip-us.apache.org/repos/asf/couchdb/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb/commit/15c31508
Tree: http://git-wip-us.apache.org/repos/asf/couchdb/tree/15c31508
Diff: http://git-wip-us.apache.org/repos/asf/couchdb/diff/15c31508

Branch: refs/heads/1684-feature-db-updates
Commit: 15c31508b95692677f7634be573724e11d274f8f
Parents: 2b8539d
Author: Jan Lehnardt <jan@apache.org>
Authored: Mon Mar 4 12:02:24 2013 +0100
Committer: Jan Lehnardt <jan@apache.org>
Committed: Mon Mar 4 14:25:12 2013 +0100

----------------------------------------------------------------------
 CHANGES                                           |    6 ++
 LICENSE                                           |    6 ++
 NEWS                                              |    2 +
 NOTICE                                            |    4 +
 configure.ac                                      |    1 +
 etc/couchdb/default.ini.tpl.in                    |    1 +
 license.skip                                      |    1 +
 share/doc/src/api/misc.rst                        |   62 ++++++++++++++
 src/Makefile.am                                   |    1 +
 src/couch_dbupdates/LICENSE                       |   22 +++++
 src/couch_dbupdates/Makefile.am                   |   33 ++++++++
 src/couch_dbupdates/NOTICE                        |    6 ++
 src/couch_dbupdates/README.md                     |   32 +++++++
 src/couch_dbupdates/src/couch_dbupdates.app.src   |   11 +++
 src/couch_dbupdates/src/couch_dbupdates.erl       |   46 ++++++++++
 src/couch_dbupdates/src/couch_dbupdates_httpd.erl |   69 ++++++++++++++++
 16 files changed, 303 insertions(+), 0 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb/blob/15c31508/CHANGES
----------------------------------------------------------------------
diff --git a/CHANGES b/CHANGES
index 184bc64..cd12973 100644
--- a/CHANGES
+++ b/CHANGES
@@ -6,6 +6,12 @@ Apache CouchDB CHANGES
 #
 # This version has not been released yet.
 #
+# HTTP Interface
+#
+#  * Added /_db_update API endpoint to get notified about creating,
+#    updating nad deleting of databases. Supports `continuous`,
+#    `longpoll` and `eventsource` `?feed=` parameter.
+#
 # Test Suite:
 #
 #  * Split up replicator_db tests into multiple independent tests.

http://git-wip-us.apache.org/repos/asf/couchdb/blob/15c31508/LICENSE
----------------------------------------------------------------------
diff --git a/LICENSE b/LICENSE
index 7d9d0ce..36b8aca 100644
--- a/LICENSE
+++ b/LICENSE
@@ -603,3 +603,9 @@ For the share/server/coffee-script.js file
   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
   OTHER DEALINGS IN THE SOFTWARE.
+
+For the src/couch_dbupdates component
+
+  2009-2012 (c) Benoît Chesneau <benoitc@e-engura.org>
+
+  Apache 2 License, see above.

http://git-wip-us.apache.org/repos/asf/couchdb/blob/15c31508/NEWS
----------------------------------------------------------------------
diff --git a/NEWS b/NEWS
index 13d395d..9fb1af2 100644
--- a/NEWS
+++ b/NEWS
@@ -11,6 +11,8 @@ Each release section notes when backwards incompatible changes have been
made.
 # -------------
 #
 # This version has not been released yet.
+#  * Added /_db_update API endpoint to get notified about creating,
+#    updating nad deleting of databases.
 
 Version 1.3.0
 -------------

http://git-wip-us.apache.org/repos/asf/couchdb/blob/15c31508/NOTICE
----------------------------------------------------------------------
diff --git a/NOTICE b/NOTICE
index 6e2090b..194505f 100644
--- a/NOTICE
+++ b/NOTICE
@@ -85,3 +85,7 @@ This product also includes the following third-party components:
  * Underscore.js 1.4.2 (http://underscorejs.org)
 
    Copyright 2012, Jeremy Ashkenas
+
+ * couch_dbupdates
+
+   Copyright 2012, Benoît Chesneau <benoitc@refuge.io>

http://git-wip-us.apache.org/repos/asf/couchdb/blob/15c31508/configure.ac
----------------------------------------------------------------------
diff --git a/configure.ac b/configure.ac
index 5246830..8d38e2d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -720,6 +720,7 @@ AC_CONFIG_FILES([share/Makefile])
 AC_CONFIG_FILES([share/doc/Makefile])
 AC_CONFIG_FILES([share/doc/build/Makefile])
 AC_CONFIG_FILES([src/Makefile])
+AC_CONFIG_FILES([src/couch_dbupdates/Makefile])
 AC_CONFIG_FILES([src/couch_index/Makefile])
 AC_CONFIG_FILES([src/couch_mrview/Makefile])
 AC_CONFIG_FILES([src/couch_replicator/Makefile])

http://git-wip-us.apache.org/repos/asf/couchdb/blob/15c31508/etc/couchdb/default.ini.tpl.in
----------------------------------------------------------------------
diff --git a/etc/couchdb/default.ini.tpl.in b/etc/couchdb/default.ini.tpl.in
index 94bf2fe..a9b0e65 100644
--- a/etc/couchdb/default.ini.tpl.in
+++ b/etc/couchdb/default.ini.tpl.in
@@ -157,6 +157,7 @@ _stats = {couch_httpd_stats_handlers, handle_stats_req}
 _log = {couch_httpd_misc_handlers, handle_log_req}
 _session = {couch_httpd_auth, handle_session_req}
 _oauth = {couch_httpd_oauth, handle_oauth_req}
+_db_updates = {couch_dbupdates_httpd, handle_req}
 
 [httpd_db_handlers]
 _all_docs = {couch_mrview_http, handle_all_docs_req}

http://git-wip-us.apache.org/repos/asf/couchdb/blob/15c31508/license.skip
----------------------------------------------------------------------
diff --git a/license.skip b/license.skip
index 89a6b05..24f702f 100644
--- a/license.skip
+++ b/license.skip
@@ -98,6 +98,7 @@
 ^src/couchdb/priv/couchspawnkillable
 ^src/couchdb/priv/stat_descriptions.cfg
 ^src/erlang-oauth/.*
+^src/couch_dbupdates
 ^src/ejson/.*
 ^src/etap/.*
 ^src/ibrowse/.*

http://git-wip-us.apache.org/repos/asf/couchdb/blob/15c31508/share/doc/src/api/misc.rst
----------------------------------------------------------------------
diff --git a/share/doc/src/api/misc.rst b/share/doc/src/api/misc.rst
index f9562ae..c33fdc1 100644
--- a/share/doc/src/api/misc.rst
+++ b/share/doc/src/api/misc.rst
@@ -33,6 +33,8 @@ A list of the available methods and URL paths are provided below:
 +--------+-------------------------+-------------------------------------------+
 | GET    | /_all_dbs               |  Get a list of all the DBs                |
 +--------+-------------------------+-------------------------------------------+
+| GET    | /_db_updates            |  A feed of database events                |
++--------+-------------------------+-------------------------------------------+
 | GET    | /_log                   |  Return the server log file               |
 +--------+-------------------------+-------------------------------------------+
 | POST   | /_replicate             |  Set or cancel replication                |
@@ -153,6 +155,66 @@ The return is a JSON array:
        "locations"
     ]
 
+``GET /_db_updates``
+====================
+
+* **Method**: ``GET /_db_updates``
+* **Request**: None
+* **Admin Privileges Required**: yes
+* **Query ARguments**:
+
+  * **Argument**: feed
+
+    * **Descroption**: Format of the response feed
+    * **Optional**: yes
+    * **Type**: string
+    * **Default**: longpoll
+    * **Supported Values**:
+
+      * **longpoll**: Closes the connection after the first event.
+      * **continuous**: Send a line of JSON per event. Keeps the socket open until ``timeout``.
+      * **eventsource**: Like, ``continuous``, but sends the events in EventSource format.
See http://dev.w3.org/html5/eventsource/ for details,
+
+  * **Argument**: timeout
+
+    * **Descroption**: Number of seconds until CouchDB closes the connection.
+    * **Optional**: yes
+    * **Type**: numeric
+    * **Default**: 60
+
+  * **Argument**: heartbeat
+
+    * **Descroption**: Number of seconds until CouchDB sends a sole newline ``\n`` character
so the client know the connection is still open, there are just no events occuring.
+    * **Optional**: yes
+    * **Type**: boolean
+    * **Default**: true
+
+* **Return Codes**:
+
+  * **200**
+    Request completed successfully.
+
+Returns a list of all database events in the CouchDB instance.
+
+A database event is one of `created`, `updated`, `deleted`.
+
+For example:
+
+.. code-block:: http
+
+    GET http://couchdb:5984/_db_events?feed=continuous
+    Accept: application/json
+
+.. code-block:: javascript
+
+    {"dbname":"my-database", "type":"created"}
+    {"dbname":"my-database", "type":"updated"}
+    {"dbname":"another-database", "type":"created"}
+    {"dbname":"my-database", "type":"deleted"}
+    {"dbname":"another-database", "type":"updated"}
+
+
+
 ``GET /_log``
 =============
 

http://git-wip-us.apache.org/repos/asf/couchdb/blob/15c31508/src/Makefile.am
----------------------------------------------------------------------
diff --git a/src/Makefile.am b/src/Makefile.am
index fbd514c..7b11e15 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -11,6 +11,7 @@
 ## the License.
 
 SUBDIRS = \
+    couch_dbupdates \
     couch_index \
     couch_mrview \
     couch_replicator \

http://git-wip-us.apache.org/repos/asf/couchdb/blob/15c31508/src/couch_dbupdates/LICENSE
----------------------------------------------------------------------
diff --git a/src/couch_dbupdates/LICENSE b/src/couch_dbupdates/LICENSE
new file mode 100644
index 0000000..a089916
--- /dev/null
+++ b/src/couch_dbupdates/LICENSE
@@ -0,0 +1,22 @@
+2009-2012 (c) Benoît Chesneau <benoitc@e-engura.org>
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.

http://git-wip-us.apache.org/repos/asf/couchdb/blob/15c31508/src/couch_dbupdates/Makefile.am
----------------------------------------------------------------------
diff --git a/src/couch_dbupdates/Makefile.am b/src/couch_dbupdates/Makefile.am
new file mode 100644
index 0000000..d131b9b
--- /dev/null
+++ b/src/couch_dbupdates/Makefile.am
@@ -0,0 +1,33 @@
+## Licensed under the Apache License, Version 2.0 (the "License"); you may not
+## use this file except in compliance with the License. You may obtain a copy of
+## the License at
+##
+##   http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing, software
+## distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+## WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+## License for the specific language governing permissions and limitations under
+## the License.
+
+couch_dbupdateslibdir = $(localerlanglibdir)/couch_dbupdates-0.1
+couch_dbupdatesebindir = $(couch_dbupdateslibdir)/ebin
+
+couch_dbupdatesebin_DATA = $(compiled_files)
+
+EXTRA_DIST = $(source_files)
+CLEANFILES = $(compiled_files)
+
+source_files = \
+    src/couch_dbupdates.erl \
+    src/couch_dbupdates.app.src \
+    src/couch_dbupdates_httpd.erl
+
+compiled_files = \
+    ebin/couch_dbupdates.beam \
+    ebin/couch_dbupdates_httpd.beam
+
+ebin/%.beam: src/%.erl
+	@mkdir -p ebin/
+	$(ERLC) -I$(top_srcdir)/src/couchdb -o ebin/ $(ERLC_FLAGS) ${TEST} $<;
+

http://git-wip-us.apache.org/repos/asf/couchdb/blob/15c31508/src/couch_dbupdates/NOTICE
----------------------------------------------------------------------
diff --git a/src/couch_dbupdates/NOTICE b/src/couch_dbupdates/NOTICE
new file mode 100644
index 0000000..ee00a85
--- /dev/null
+++ b/src/couch_dbupdates/NOTICE
@@ -0,0 +1,6 @@
+couch_dbupdates
+---------------
+
+2012 (c) Benoît Chesneau <benoitc@refuge.io>
+
+couch_dbupdates is released under the Apache License 2.

http://git-wip-us.apache.org/repos/asf/couchdb/blob/15c31508/src/couch_dbupdates/README.md
----------------------------------------------------------------------
diff --git a/src/couch_dbupdates/README.md b/src/couch_dbupdates/README.md
new file mode 100644
index 0000000..c683102
--- /dev/null
+++ b/src/couch_dbupdates/README.md
@@ -0,0 +1,32 @@
+# couch_dbupdates
+
+`couch_dbupdates` is a simple couchdb modules to receive databases
+events in couchdb node.
+
+It's actually **supported by all the [refuge](http://refuge.io) projects**:
+
+- [refuge](https://github.com/refuge/refuge)
+- [rcouch](https://github.com/refuge/rcouch)
+- [rcouch_template](https://github.com/refuge/rcouch_template)
+
+
+## HTTP API
+
+To get db events, do a GET to `/_db_updates` .
+
+You can pass an optional query parameters:
+
+* `feed` The feed can be `longpoll` (default) for longpolling, `eventsource`
+  for event stream or `continuous` for continuous feed.
+* `timeout`: timeout before the longpolling connection close or when the
+  heartbeat is emitted.
+* `heartbeat`: true, or false. an empty line is emittend when the
+  timeout occurs to maintain the connection active.
+
+
+## Example of usage
+
+    $ curl http://127.0.0.1:5984/_db_updates?feed=continuous
+    {"type":"created","db_name":"testdb"}
+    {"type":"updated","db_name":"testdb"}
+    {"type":"deleted","db_name":"testdb"}

http://git-wip-us.apache.org/repos/asf/couchdb/blob/15c31508/src/couch_dbupdates/src/couch_dbupdates.app.src
----------------------------------------------------------------------
diff --git a/src/couch_dbupdates/src/couch_dbupdates.app.src b/src/couch_dbupdates/src/couch_dbupdates.app.src
new file mode 100644
index 0000000..c420283
--- /dev/null
+++ b/src/couch_dbupdates/src/couch_dbupdates.app.src
@@ -0,0 +1,11 @@
+{application, couch_dbupdates,
+ [
+  {description, ""},
+  {vsn, "@version@"},
+  {registered, []},
+  {applications, [
+                  kernel,
+                  stdlib
+                 ]},
+  {env, []}
+ ]}.

http://git-wip-us.apache.org/repos/asf/couchdb/blob/15c31508/src/couch_dbupdates/src/couch_dbupdates.erl
----------------------------------------------------------------------
diff --git a/src/couch_dbupdates/src/couch_dbupdates.erl b/src/couch_dbupdates/src/couch_dbupdates.erl
new file mode 100644
index 0000000..e37362f
--- /dev/null
+++ b/src/couch_dbupdates/src/couch_dbupdates.erl
@@ -0,0 +1,46 @@
+-module(couch_dbupdates).
+
+-export([handle_dbupdates/3]).
+
+
+handle_dbupdates(Fun, Acc, Options) ->
+    NotifierPid = db_update_notifier(),
+    try
+        loop(Fun, Acc, Options)
+    after
+        couch_db_update_notifier:stop(NotifierPid)
+    end.
+
+
+loop(Fun, Acc, Options) ->
+    [{timeout, Timeout}, {heartbeat, Heartbeat}] = Options,
+    receive
+        {db_updated, Event} ->
+            case Fun(Event, Acc) of
+                {ok, Acc1} ->
+                    loop(Fun, Acc1, Options);
+                stop ->
+                    Fun(stop, Acc)
+
+            end
+    after Timeout ->
+        case Heartbeat of
+            true ->
+                case Fun(heartbeat, Acc) of
+                {ok, Acc1} ->
+                    loop(Fun, Acc1, Options);
+                stop ->
+                    Fun(stop, Acc)
+
+                end;
+            _ ->
+                Fun(stop, Acc)
+        end
+    end.
+
+db_update_notifier() ->
+    Self = self(),
+    {ok, Notifier} = couch_db_update_notifier:start_link(fun(Event) ->
+        Self ! {db_updated, Event}
+    end),
+    Notifier.

http://git-wip-us.apache.org/repos/asf/couchdb/blob/15c31508/src/couch_dbupdates/src/couch_dbupdates_httpd.erl
----------------------------------------------------------------------
diff --git a/src/couch_dbupdates/src/couch_dbupdates_httpd.erl b/src/couch_dbupdates/src/couch_dbupdates_httpd.erl
new file mode 100644
index 0000000..96058d3
--- /dev/null
+++ b/src/couch_dbupdates/src/couch_dbupdates_httpd.erl
@@ -0,0 +1,69 @@
+-module(couch_dbupdates_httpd).
+
+-export([handle_req/1]).
+
+-include_lib("couch_db.hrl").
+
+-record(state, {resp, feed}).
+
+handle_req(#httpd{method='GET'}=Req) ->
+    ok = couch_httpd:verify_is_server_admin(Req),
+    Qs = couch_httpd:qs(Req),
+    Feed = proplists:get_value("feed", Qs, "longpoll"),
+
+    Timeout = list_to_integer(
+                proplists:get_value("timeout", Qs, "60000")
+    ),
+
+    Heartbeat0 = proplists:get_value("heartbeat", Qs),
+    Heartbeat = case {Feed, Heartbeat0} of
+        {"longpoll", _} -> false;
+        {_, "false"} -> false;
+        _ -> true
+    end,
+
+    Options = [{timeout, Timeout}, {heartbeat, Heartbeat}],
+
+    {ok, Resp} = case Feed of
+        "eventsource" ->
+            Headers = [
+                {"Content-Type", "text/event-stream"},
+                {"Cache-Control", "no-cache"}
+            ],
+            couch_httpd:start_json_response(Req, 200, Headers);
+        _ ->
+            couch_httpd:start_json_response(Req, 200)
+    end,
+
+    State = #state{resp=Resp, feed=Feed},
+    couch_dbupdates:handle_dbupdates(fun handle_update/2,
+                                     State, Options).
+
+handle_req(Req, _Db) ->
+    couch_httpd:send_method_not_allowed(Req, "GET").
+
+handle_update(stop, #state{resp=Resp}) ->
+    couch_httpd:end_json_response(Resp);
+handle_update(heartbeat, #state{resp=Resp}=State) ->
+    {ok, Resp1} = couch_httpd:send_chunk(Resp, "\n"),
+    {ok, State#state{resp=Resp1}};
+handle_update(Event, #state{resp=Resp, feed="eventsource"}=State) ->
+    EventObj = event_obj(Event),
+    {ok, Resp1} = couch_httpd:send_chunk(Resp, ["data: ",
+                                                ?JSON_ENCODE(EventObj),
+                                                "\n\n"]),
+    {ok, State#state{resp=Resp1}};
+handle_update(Event, #state{resp=Resp, feed="continuous"}=State) ->
+    EventObj = event_obj(Event),
+    {ok, Resp1} = couch_httpd:send_chunk(Resp, [?JSON_ENCODE(EventObj) |
+                            "\n"]),
+    {ok, State#state{resp=Resp1}};
+handle_update(Event, #state{resp=Resp, feed="longpoll"}) ->
+    {Props} = event_obj(Event),
+    JsonObj = {[{<<"ok">>, true} | Props]},
+    couch_httpd:send_chunk(Resp, ?JSON_ENCODE(JsonObj)),
+    stop.
+
+event_obj({Type, DbName}) ->
+    {[{<<"type">>, couch_util:to_binary(Type)},
+      {<<"db_name">>, couch_util:to_binary(DbName)}]}.


Mime
View raw message