2015-05-29 15:39 GMT+02:00 Cédric Krier <[email protected]>:
> On 29 May 14:40, Albert Cervera i Areny wrote:
>> 2015-05-29 13:14 GMT+02:00 Raimon Esteve <[email protected]>:
>> > Hie,
>> >
>> > when assign stock move, try_assign lock table (1). In Backend
>> > PostgresSQL, the lock is NOWAIT (2).
>> >
>> > When two or more users try to assign shipments at same time, "second
>> > user" get a nice error.
>> >
>> > Traceback is:
>> >
>> >   File "/shipment.py", line 1292, in assign_try
>> >     for m in s.inventory_moves]):
>> >   File "/move.py", line 754, in assign_try
>> >     Transaction().cursor.lock(cls._table)
>> >   File "/trytond/backend/postgresql/database.py", line 359, in lock
>> >     self.cursor.execute('LOCK "%s" IN EXCLUSIVE MODE NOWAIT' % table)
>> > OperationalError: could not obtain lock on relation "stock_move"
>> >
>> > Why lock() method in PSQL backend add NOWAIT option? Why not waiting
>> > next user request when unluck table and continue try_assin? the
>> > reason?
>> >
>> > About NOWAIT: If NOWAIT is specified, LOCK TABLE does not wait to
>> > acquire the desired lock
>>
>> Also note that tryton locks the whole table even when two users are
>> not competing for the same product.
>>
>> I created a review [1] some time ago to fix that although it
>> eventually was commited something much simpler, you can dig in the
>> reviews, where per product advisory locks were used.
>
> Because it doesn't work. It will require a lot of extrat code to be
> managed correctly: lock at creation, on both side of the write, on
> delete etc.
>

I've been revisiting this issue, I don't understand why a lock is
necessary outside assign_try.

Let me put an scenario:

There's 1 unit of product A on warehouse X.

There are two concurrent transactions:

a) does assign_try to try to ship the product to a customer
b) moves the product from warehouse X to warehouse Z without
assign_try (that may include a write, create, or delete, doesn't
really matter for the case)

So let's see what happens with and without those locks.

If we just have the lock on assign_try there can be two possibilities:

1.- a) is executed *after* b) so as the product has been moved from X
to Z and there are 0 units of product A in X, assign_try "fails" and
stock can not be picked
2.- a) is executed *before* b) so we deliver the goods to the customer
*and* also make the move from X to Z which means that the stock of
product A is no -1 on warehouse X

We probably don't want the second scenario so we would add the
suggested lock on write/create/delete.

BUT what happens if those transactions are NOT concurrent and we DO
have the lock?

Take the second possibility where a) is executed *before* b). What
happens is that we end up having -1 units of product A on warehouse X
anyway.

What I see is that as long as you want to ensure that the reservation
process works as expected *all* stock moves must go through
*assign_try* because it is this workflow that ensures the expected
behaviour, not the lock mechanism.

So I don't see any reason why we should add the lock anywhere else
apart from assign_try.

What am I missing?

>> I think sooner or later some solution that is more fine grained than
>> the current table lock will be required.
>
> I don't think so if we can keep transaction execution fast enough, it is
> just a matter of keeping the queue of waiting transaction small enough.
> More over, companies that will have a such huge amount of products and
> shipments to process at the same time will require to have a custom
> workflow that doesn't contain assignation process but just picking on
> the fly.
>
>> [1] http://tryton-rietveld-hrd.appspot.com/999002/
> --
> Cédric Krier - B2CK SPRL
> Email/Jabber: [email protected]
> Tel: +32 472 54 46 59
> Website: http://www.b2ck.com/



-- 
Albert Cervera i Areny
Tel. 93 553 18 03
@albertnan
www.NaN-tic.com

Reply via email to