couchdb-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Metin Akat <>
Subject Re: FIFO/LIFO accountancy
Date Wed, 03 Feb 2010 18:07:42 GMT
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.

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

View raw message