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
