Before I check this in, can someone add to the patch support for this in the couch.js library too?

That is, when creating a new document, library either generates a UUID locally (if the browser supports it) or via a GET to CouchDB. And ideally it would cache a bunch in memory so it's not necessary to get a new one for each document save. This work needs to be done both for single document creation and documents created via in a bulk post.

Once we have that in the patch, I'll check it in. We also need to update the wiki about the proper way to create a document.

-Damien


On Jul 24, 2008, at 1:15 AM, Michael Hendricks wrote:

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 <[EMAIL PROTECTED]>
---
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


Reply via email to