couchdb-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Andrew Melo <>
Subject Re: FIFO/LIFO accountancy
Date Wed, 03 Feb 2010 18:13:37 GMT
On Wed, Feb 3, 2010 at 12:07 PM, Metin Akat <> wrote:
> Hmm, one solution I hadn't thought about at all.
> Thanks, Chris. I'll think about it.
> So far the only difference is that I would probably choose the leading
> event to be the document of purchase.
> Then in a situation of race condition usually there won't be the need
> to "raise an exception". Instead the   "FIFO process" will continue
> with the next "batch". An exception will be risen only if we are out
> of apples, and then we will issue a "cancellation of purchase"
> document, or even better, will put the purchase order on queue (in a
> case it makes sense) and order new apples from our supplier.
> Yeah, I'm starting to like such an approach. Thanks again.

What happens to the customer then? You've shown me a page saying
"order complete" and then at some point down the line (whenever
couchDB notices the probem or your state machine catches up on
_changes), it realizes it can't fulfill the order. Even worse, all of
the cheaper apples are actually gone, and all that's left are the more
expensive ones.

I think your better bet would be to use something that was aware of
atomic commits handle the inventory-ing, and then export that data
couch to run map/reduce over, rather than hoping to enforce atomic
semantics on what is an unatomic subsystem.


> On Wed, Feb 3, 2010 at 7:27 PM, Chris Anderson <> wrote:
>> 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

Andrew Melo

View raw message