You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by da...@apache.org on 2008/08/08 23:06:30 UTC

svn commit: r684092 - in /incubator/couchdb/trunk: share/www/script/couch.js share/www/script/couch_tests.js src/couchdb/couch_httpd.erl

Author: damien
Date: Fri Aug  8 14:06:29 2008
New Revision: 684092

URL: http://svn.apache.org/viewvc?rev=684092&view=rev
Log:
Idempotent document creation support, new HTTP api to generate UUIDs and support in the couch.js library for using them. Creating uuids client side ensure that document creation happens only once, despite automatic network retries.

Modified:
    incubator/couchdb/trunk/share/www/script/couch.js
    incubator/couchdb/trunk/share/www/script/couch_tests.js
    incubator/couchdb/trunk/src/couchdb/couch_httpd.erl

Modified: incubator/couchdb/trunk/share/www/script/couch.js
URL: http://svn.apache.org/viewvc/incubator/couchdb/trunk/share/www/script/couch.js?rev=684092&r1=684091&r2=684092&view=diff
==============================================================================
--- incubator/couchdb/trunk/share/www/script/couch.js [utf-8] (original)
+++ incubator/couchdb/trunk/share/www/script/couch.js [utf-8] Fri Aug  8 14:06:29 2008
@@ -42,18 +42,14 @@
   this.save = function(doc, options) {
     var req;
     if (doc._id == undefined)
-      req = request("POST", this.uri + encodeOptions(options), {
-        body: JSON.stringify(doc)
-      });
-    else
-      req = request("PUT", this.uri  + encodeURIComponent(doc._id) + encodeOptions(options), {
-        body: JSON.stringify(doc)
-      });
+      doc._id = CouchDB.newUuids(1)[0];
+
+    req = request("PUT", this.uri  + encodeURIComponent(doc._id) + encodeOptions(options), {
+      body: JSON.stringify(doc)
+    });
     var result = JSON.parse(req.responseText);
     if (req.status != 201)
       throw result;
-    // set the _id and _rev members on the input object, for caller convenience.
-    doc._id = result.id;
     doc._rev = result.rev;
     return result;
   }
@@ -91,6 +87,18 @@
   }
   
   this.bulkSave = function(docs, options) {
+    // first prepoulate the UUIDs for new documents
+    var newCount = 0
+    for (var i=0; i<docs.length; i++) {
+      if (docs[i]._id == undefined)
+        newCount++;
+    }
+    var newUuids = CouchDB.newUuids(docs.length);
+    var newCount = 0
+    for (var i=0; i<docs.length; i++) {
+      if (docs[i]._id == undefined)
+        docs[i]._id = newUuids.pop();
+    }
     var req = request("POST", this.uri + "_bulk_docs" + encodeOptions(options), {
       body: JSON.stringify({"docs": docs})
     });
@@ -98,7 +106,6 @@
     if (req.status != 201)
       throw result;
     for (var i = 0; i < docs.length; i++) {
-        docs[i]._id = result.new_revs[i].id;
         docs[i]._rev = result.new_revs[i].rev;
     }
     return result;
@@ -232,3 +239,26 @@
   req.send(options.body || "");
   return req;
 }
+
+CouchDB.uuids_cache = [];
+
+CouchDB.newUuids = function(n) {
+    if (CouchDB.uuids_cache.length >= n) {
+      var uuids = CouchDB.uuids_cache.slice(CouchDB.uuids_cache.length - n);
+      if(CouchDB.uuids_cache.length - n == 0) {
+        CouchDB.uuids_cache = [];
+      } else {
+        CouchDB.uuids_cache =
+            CouchDB.uuids_cache.slice(0, CouchDB.uuids_cache.length - n);
+      }
+      return uuids;
+    } else {
+      var req = CouchDB.request("POST", "/_uuids?count=" + (100 + n));
+      var result = JSON.parse(req.responseText);
+      if (req.status != 200)
+        throw result;
+      CouchDB.uuids_cache =
+          CouchDB.uuids_cache.concat(result.uuids.slice(0, 100));
+      return result.uuids.slice(100);
+    }
+  }

Modified: incubator/couchdb/trunk/share/www/script/couch_tests.js
URL: http://svn.apache.org/viewvc/incubator/couchdb/trunk/share/www/script/couch_tests.js?rev=684092&r1=684091&r2=684092&view=diff
==============================================================================
--- incubator/couchdb/trunk/share/www/script/couch_tests.js [utf-8] (original)
+++ incubator/couchdb/trunk/share/www/script/couch_tests.js [utf-8] Fri Aug  8 14:06:29 2008
@@ -194,6 +194,42 @@
     }
   },
 
+  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 xhr = CouchDB.request("POST", "/_uuids");
+    T(xhr.status == 200);
+    var result = JSON.parse(xhr.responseText);
+    T(result.uuids.length == 1);
+    var first = result.uuids[0];
+
+    // a single UUID with an explicit count
+    xhr = CouchDB.request("POST", "/_uuids?count=1");
+    T(xhr.status == 200);
+    result = JSON.parse(xhr.responseText);
+    T(result.uuids.length == 1);
+    var second = result.uuids[0];
+    T(first != second);
+
+    // no collisions with 1,000 UUIDs
+    xhr = CouchDB.request("POST", "/_uuids?count=1000");
+    T(xhr.status == 200);
+    result = JSON.parse(xhr.responseText);
+    T( result.uuids.length == 1000 );
+    var seen = {};
+    for(var i in result.uuids) {
+      var id = result.uuids[i];
+      T(seen[id] === undefined);
+      seen[id] = 1;
+    }
+    
+    // check our library
+  },
+  
   bulk_docs: function(debug) {
     var db = new CouchDB("test_suite_db");
     db.deleteDb();

Modified: incubator/couchdb/trunk/src/couchdb/couch_httpd.erl
URL: http://svn.apache.org/viewvc/incubator/couchdb/trunk/src/couchdb/couch_httpd.erl?rev=684092&r1=684091&r2=684092&view=diff
==============================================================================
--- incubator/couchdb/trunk/src/couchdb/couch_httpd.erl (original)
+++ incubator/couchdb/trunk/src/couchdb/couch_httpd.erl Fri Aug  8 14:06:29 2008
@@ -97,6 +97,8 @@
             handle_replicate_request(Req, Method);
         "/_restart" ->
             handle_restart_request(Req, Method);
+        "/_uuids" ->
+            handle_uuids_request(Req, Method);
         "/_utils" ->
             {ok, Req:respond({301, [
                 {"Location", "/_utils/"}
@@ -148,6 +150,17 @@
 handle_restart_request(_Req, _Method) ->
     throw({method_not_allowed, "POST"}).
 
+handle_uuids_request(Req, 'POST') ->
+    Count = list_to_integer(proplists:get_value("count", Req:parse_qs(), "1")),
+    % generate the uuids
+    UUIDs = [ couch_util:new_uuid() || _ <- 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, "POST"}).
+
+
 % Database request handlers
 
 handle_db_request(Req, Method, {Path}) ->



Re: svn commit: r684092 - in /incubator/couchdb/trunk: share/www/script/couch.js share/www/script/couch_tests.js src/couchdb/couch_httpd.erl

Posted by Damien Katz <da...@apache.org>.
What Chris said :)


On Aug 8, 2008, at 6:26 PM, Chris Anderson wrote:

> On Fri, Aug 8, 2008 at 3:11 PM, Michael Hendricks  
> <mi...@ndrix.org> wrote:
>> why did you change the
>> _uuids API from a GET request to a POST?
>>
>
> POST makes sense because under no circumstances do you want a UUID
> reused or cached.
>
> -- 
> Chris Anderson
> http://jchris.mfdz.com


Re: svn commit: r684092 - in /incubator/couchdb/trunk: share/www/script/couch.js share/www/script/couch_tests.js src/couchdb/couch_httpd.erl

Posted by Chris Anderson <jc...@grabb.it>.
On Fri, Aug 8, 2008 at 3:11 PM, Michael Hendricks <mi...@ndrix.org> wrote:
> why did you change the
> _uuids API from a GET request to a POST?
>

POST makes sense because under no circumstances do you want a UUID
reused or cached.

-- 
Chris Anderson
http://jchris.mfdz.com

Re: svn commit: r684092 - in /incubator/couchdb/trunk: share/www/script/couch.js share/www/script/couch_tests.js src/couchdb/couch_httpd.erl

Posted by Michael Hendricks <mi...@ndrix.org>.
On Fri, Aug 08, 2008 at 09:06:30PM -0000, damien@apache.org wrote:
> Author: damien
> Date: Fri Aug  8 14:06:29 2008
> New Revision: 684092
> 
> URL: http://svn.apache.org/viewvc?rev=684092&view=rev
> Log:
> Idempotent document creation support, new HTTP api to generate UUIDs
> and support in the couch.js library for using them. Creating uuids
> client side ensure that document creation happens only once, despite
> automatic network retries.

Thanks Damien.  I had planned on sending a follow up patch to implement
these features as you requested but I wasn't able to schedule it in this
week.  I had one question about your commit so that I can improve my
mental model before sending future patches: why did you change the
_uuids API from a GET request to a POST?

-- 
Michael