On Wed, Feb 3, 2010 at 8:37 AM, Brian Candler wrote: > On Wed, Feb 03, 2010 at 05:29:26PM +0200, Metin Akat wrote: >> So, we need some way to figure out which apples we sell first. (how >> much value to remove from the warehouse account). In order to do this >> we need to know how much have we sold till the moment. And this needs >> to be fault tolerant. >> For example, if somebody (at some other cash register in the store) >> sold 3 apples before our deal, our transactions would be quite a bit >> different. What if this happened one milisecond before we sell our >> apples? > > It sounds to me like this is a locking problem. You have an inventory of > (5 apples @ $2), (5 apples @ $3) and you want to remove from these pools > atomically, *without any chance of going negative* > You can do a state machine approach where you have 1 update "pull the apples off the shelf" and another one for the cash register. The register in this case would be an asynchronous background process. If you have a crash between pulling the apples of the shelf and the cash register, but the register is driven by _changes, it'll just pick right up after a crash. If you have a race condition and 2 users add the apples to their carts, whoever the cash register services first wins. The other user can get a "delayed shipping option" error message. > So your first thought might be to keep your stock of apples as a single > document, and use couchdb's 'optimistic locking' to prevent two concurrent > changes: > > { >  "id":"apples", >  "stock":{2.0=>5, 3.0=>5},  // cost price => quantity > } > > That's fine (on a single couchdb node anyway). But then you want to record > the sale as another part of the same 'transaction', and post it to your > sales ledger and the customer's account receivable at the same time.  That > might work if the details of the sale were stored in the same document as > the apples (a view can pull them out). e.g. > > { >  "id":"apples", >  "stock":{3.0=>4}, >  "purchases":[ >   {"supplier":888, "orderno":123, "line":1, "qty":5, "cost":10.0}, >   {"supplier":888, "orderno":124, "line":1, "qty":5, "cost":15.0} >  ], >  "sales":[ >  {"cust":1234, "orderno":9999, "line":1, "qty":6, "price":30.0, "cost":13.0} >  ] > } > > But what if one customer decides to purchase apples and pears in the same > order?  In the event of a power loss, would it be acceptable for half of the > order to be recorded? > > I think it might. If the order is a separate doc, and the order ID is posted > against each line item as shown above, you can identify orders which haven't > been fully processed and hence complete the processing of them when the app > restarts. > > This gives a very stock-centric view of your business processes. What if > your business takes apples out of the apples stock and manufactures it into > cartons of apple juice, which it then sells? > > Maybe an RDBMS would be a better fit :-( > > B. > -- Chris Anderson http://jchrisa.net http://couch.io