Dear Wiki user,

You have subscribed to a wiki page or wiki category on "Couchdb Wiki" for 
change notification.

The following page has been changed by JanLehnardt:
http://wiki.apache.org/couchdb/Frequently_asked_questions

The comment on the change is:
add transactions FaQ

------------------------------------------------------------------------------
    * [#how_replication How Do I Use Replication?]
    * [#how_find_conflicts How do I find out which conflicts occurred during 
replication]
    * [#how_spread_load How can I spread load across multiple nodes?]
-   * [#how_fast_views How Fast are CouchDB Views?]
    * [#why_no_mnesia Why Does CouchDB Not Use Mnesia?]
    * [#i_can_has_no_http Can I talk to CouchDB without going through the HTTP 
API?]
    * [#unicode_data Erlang has been slow to adopt Unicode. Is Unicode or UTF-8 
a problem with CouchDB?]
+   * [#transactions How do I use transactions with CouchDB?]
  
  === Views ===
+   * [#how_fast_views How Fast are CouchDB Views?]
    * [#update_views_more_often I want to update my view indexes more often 
than only when a user reads it. How do I do that best?]
    * [#slow_view_building Creating my view index takes ages, WTF?]
    * [#relationships How do I model relationships in CouchDB? / Where are my 
JOINs?]
@@ -127, +128 @@

  == Can I talk to CouchDB without going through the HTTP API? ==
  
  CouchDB's data model and internal API map the REST/HTTP model so well that 
any other API would basically reinvent some flavour of HTTP. However, there is 
a plan to refactor CouchDB's internals so as to provide a documented Erlang API.
+ 
+ [[Anchor(transactions)]]
+ == How do I use transactions with CouchDB? ==
+ 
+ CouchDB uses an "optimistic concurrency" model. In the simplest terms, this 
just means that you send a document version along with your update, and CouchDB 
rejects the change if the current document version doesn't match what you've 
sent.
+ 
+ It's deceptively simple, really. You can reframe many normal transaction 
based scenarios for CouchDB. You do need to sort of throw out your RDBMS domain 
knowledge when learning CouchDB, though. It's helpful to approach problems from 
a higher level, rather than attempting to mold Couch to a SQL based world.
+ 
+ Keeping track of inventory
+ 
+ The problem you outlined is primarily an inventory issue. If you have a 
document describing an item, and it includes a field for "quantity available", 
you can handle concurrency issues like this:
+ 
+ Retrieve the document, take note of the _rev property that CouchDB sends along
+ Decrement the quantity field, if it's greater than zero
+ Send the updated document back, using the _rev property
+ If the _rev matches the currently stored number, be done!
+ If there's a conflict (when _rev doesn't match), retrieve the newest document 
version
+ In this instance, there are two possible failure scenarios to think about. If 
the most recent document version has a quantity of 0, you handle it just like 
you would in a RDBMS and alert the user that they can't actually buy what they 
wanted to purchase. If the most recent document version has a quantity greater 
than 0, you simply repeat the operation with the updated data, and start back 
at the beginning. This forces you to do a bit more work than an RDBMS would, 
and could get a little annoying if there are frequent, conflicting updates.
+ 
+ Now, the answer I just gave presupposes that you're going to do things in 
CouchDB in much the same way that you would in an RDBMS. I might approach this 
problem a bit differently:
+ 
+ I'd start with a "master product" document that includes all the descriptor 
data (name, picture, description, price, etc). Then I'd add an "inventory 
ticket" document for each specific instance, with fields for product_key and 
claimed_by. If you're selling a model of hammer, and have 20 of them to sell, 
you might have documents with keys like hammer-1, hammer-2, etc, to represent 
each available hammer.
+ 
+ Then, I'd create a view that gives me a list of available hammers, with a 
reduce function that lets me see a "total". These are completely off the cuff, 
but should give you an idea of what a working view would look like.
+ 
+ Map
+ 
+ {{{
+ function(doc) 
+ { 
+     if (doc.type == 'inventory_ticket' && doc.claimed_by == null ) { 
+         emit(doc.product_key, { 'inventory_ticket' :doc.id, '_rev' : doc._rev 
}); 
+     } 
+ }
+ }}}
+ 
+ This gives me a list of available "tickets", by product key. I could grab a 
group of these when someone wants to buy a hammer, then iterate through sending 
updates (using the id and _rev) until I successfully claim one (previously 
claimed tickets will result in an update error).
+ 
+ Reduce
+ 
+ {{{
+ function (keys, values, combine) {
+     return values.length;
+ }
+ }}}
+ This reduce function simply returns the total number of unclaimed 
inventory_ticket items, so you can tell how many "hammers" are available for 
purchase.
+ 
+ Caveats
+ 
+ This solution represents roughly 3.5 minutes of total thinking for the 
particular problem you've presented. There may be better ways of doing this! 
That said, it does substantially reduce conflicting updates, and cuts down on 
the need to respond to a conflict with a new update. Under this model, you 
won't have multiple users attempting to change data in primary product entry. 
At the very worst, you'll have multiple users attempting to claim a single 
ticket, and if you've grabbed several of those from your view, you simply move 
on to the next ticket and try again
+ 
+ (This FaQ entry was borrowed from 
[http://stackoverflow.com/questions/299723/can-i-do-transactions-and-locks-in-couchdb]
 with permission from the author.)
  
  [[Anchor(update_views_more_often)]]
  == I want to update my view indexes more often than only when a user reads 
it. How do I do that best? ==

Reply via email to