incubator-couchdb-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Chris Anderson <jch...@apache.org>
Subject Re: FIFO/LIFO accountancy
Date Wed, 03 Feb 2010 17:27:34 GMT
On Wed, Feb 3, 2010 at 8:37 AM, Brian Candler <B.Candler@pobox.com> 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

Mime
View raw message