couchdb-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Michael Hendricks <mich...@ndrix.org>
Subject [PATCH] Expose UUID generation through the REST API
Date Thu, 24 Jul 2008 05:15:31 GMT
Because a POST request to create a new document is not idempotent, PUT
requests should be used when possible.  Unfortunately, generating a
sufficiently random document identifier from JavaScript is slightly
difficult.  To make the process easier, this patch exposes CouchDB's
functionality for generating UUIDs so that it's accessible with an
HTTP request.

This patch implements a new CouchDB URI _uuids which responds to
GET requests with a JSON object something like this:

    {
        "uuids" : [
            "405f021c2bdfee1cb0ead93b0864c2d2",
            "512d8fecc3f9a421a902f0815e5cbc3f",
            "fc5be6230fcffd061af50169ecb1647f"
        ],
    }

The number of UUIDs returned is specified with a "count" query
parameter.  The count parameter defaults to 1.

Signed-off-by: Michael Hendricks <michael@ndrix.org>
---
 share/www/script/couch.js       |   11 +++++++++++
 share/www/script/couch_tests.js |   33 +++++++++++++++++++++++++++++++++
 src/couchdb/couch_httpd.erl     |   18 ++++++++++++++++++
 3 files changed, 62 insertions(+), 0 deletions(-)

diff --git a/share/www/script/couch.js b/share/www/script/couch.js
index 38c9cf3..fc6f8b0 100644
--- a/share/www/script/couch.js
+++ b/share/www/script/couch.js
@@ -160,6 +160,17 @@ function CouchDB(name) {
     return result;
   }
 
+  this.uuids = function(count) {
+    var uri = "/_uuids";
+    if (count) uri = uri + "?count=" + count;
+    var req = request("GET", uri);
+    var result = JSON.parse(req.responseText);
+    if (req.status != 200)
+      throw result;
+    return result;
+  }
+
+
   // Convert a options object to an url query string.
   // ex: {key:'value',key2:'value2'} becomes '?key="value"&key2="value2"'
   function encodeOptions(options) {
diff --git a/share/www/script/couch_tests.js b/share/www/script/couch_tests.js
index 852f9cf..711e3c1 100644
--- a/share/www/script/couch_tests.js
+++ b/share/www/script/couch_tests.js
@@ -1338,6 +1338,39 @@ var tests = {
     T(xhr.getResponseHeader("Content-Type") == "text/plain")
     T(db.info().doc_count == 1);
     T(db.info().disk_size < deletesize);
+  },
+
+  uuids: function(debug) {
+    var db = new CouchDB("test_suite_db");
+    db.deleteDb();
+    db.createDb();
+    if (debug) debugger;
+
+    // a single UUID without an explicit count
+    var result = db.uuids();
+    T(result.uuids.length == 1);
+    var first = result.uuids[0];
+
+    // a single UUID with an explicit count
+    result = db.uuids(1);
+    T( result.uuids.length == 1 );
+    var second = result.uuids[0];
+    T( first != second );
+
+    // no collisions with 1,000 UUIDs
+    result = db.uuids(1000);
+    T( result.uuids.length == 1000 );
+    var seen = {};
+    for( var i in result.uuids ) {
+        var id = result.uuids[i];
+        if ( seen[id] ) {
+            seen[id]++;
+            T( seen[id] == 1 );  // this will always fail
+        }
+        else {
+            seen[id] = 1;
+        }
+    }
   }
 };
 
diff --git a/src/couchdb/couch_httpd.erl b/src/couchdb/couch_httpd.erl
index af8d9b4..d41e1ac 100644
--- a/src/couchdb/couch_httpd.erl
+++ b/src/couchdb/couch_httpd.erl
@@ -97,6 +97,8 @@ handle_request0(Req, DocumentRoot, Method, Path) ->
             handle_replicate_request(Req, Method);
         "/_restart" ->
             handle_restart_request(Req, Method);
+        "/_uuids" ->
+            handle_uuids_request(Req, Method);
         "/_utils" ->
             {ok, Req:respond({301, [
                 {"Location", "/_utils/"}
@@ -147,6 +149,22 @@ handle_restart_request(Req, 'POST') ->
 handle_restart_request(_Req, _Method) ->
     throw({method_not_allowed, "POST"}).
 
+handle_uuids_request(Req, 'GET') ->
+    Count = list_to_integer(proplists:get_value("count", Req:parse_qs(), "1")),
+    % generate the uuids
+    UUIDs = lists:map(
+        fun (_) -> couch_util:new_uuid() end,
+        lists:seq(1,Count)
+    ),
+    % send a JSON response
+    send_json(Req, {obj, [
+        {"uuids", list_to_tuple(UUIDs)}
+    ]});
+
+handle_uuids_request(_Req, _Method) ->
+    throw({method_not_allowed, "GET"}).
+
+
 % Database request handlers
 
 handle_db_request(Req, Method, {Path}) ->
-- 
1.5.6


Mime
View raw message