couchdb-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Warren Gallagher <>
Subject Re: FIFO/LIFO accountancy
Date Wed, 03 Feb 2010 18:30:50 GMT
I don't have a specific couchDB solution to offer, however, I have found a particular chapter
in "RESTful Web Services" by Leonard Richardson & Sam Ruby quite useful in thinking about
such problems.
In chapter 8,  "REST and ROA Best Practices" a way of modelling transactions as resources
is explained. Sometimes thinking about resource models leads to understanding underlying document
models that may be useful.

Warren Gallagher
Chief Technology Officer
GridIron Software

On 2010-02-03, at 1:13 PM, Andrew Melo wrote:

> 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.
> Best,
> Andrew
>> 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
>>>> 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

  • Unnamed multipart/alternative (inline, None, 0 bytes)
View raw message