Subversion Repositories SmartDukaan

Rev

Hide changed files | Details | Compare with Previous | Blame | RSS feed

Filtering Options

Rev Age Author Path Log message Diff Changes
37706 19 d 10 h amit /trunk/ cart: take the cart row before any line, to break a lock-ordering deadlock

InnoDB was rolling back cart edits with "Deadlock found when trying to get lock"
(GlitchTip #53, 27 deadlocks) and losing others to OptimisticLockException
"actual row count: 0; expected: 1" (11 issues, 42 events). Both are the same cause.

Two request paths took the same two rows in OPPOSITE orders. Adding a line INSERTs
into user.line, and line_cart_id_fk shared-locks the parent cart FIRST, line second.
Validation/hydration mutated the line rows FIRST and wrote cart.total_price second.
Run those concurrently on one cart and it is a cycle. Caught in the act on prod:

T1: INSERT user.line (cart_id=175180781) -> holds S on cart, waits S on line
T2: UPDATE user.cart SET total_price=269340.0, version=175 WHERE version=174
-> holds X on line, waits X on cart
*** WE ROLL BACK TRANSACTION (1)

Fix is to give every mutating path one order: cart, then lines. CartRepository gains
selectByIdForUpdate, and it is called as the first statement of each path that writes
a cart line. Re-taking it inside one request is a no-op.

A lock-ordering fix is all-or-nothing -- one path in the wrong order is enough to
re-form the cycle -- so this covers ALL TEN cart-line writers, not just the two that
happened to show up in the stack traces: createCartItem, clearCart, getCartValidation,
addItemsToCart (x2), addShoppingBag, validateForOpen (x2) and V2BillingController's
bind/unbindInsurance. The audit is worth re-running before adding another writer.

Note validateForOpen and getCartValidation WRITE despite their names (they correct
cart_line quantity/price and roll up cart.total_price), which is why a "validate" call
was ever holding write locks. The lock is placed accordingly; making those genuinely
read-only is a separate, larger change.

This also serialises concurrent edits to the SAME cart, which is what the @Version
column on Cart was already trying and failing to express. Different carts are
different rows, so there is no cost across partners.
 
/trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/cart/CartServiceImpl.java
/trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/cart/v2/CartValidationServiceImpl.java
/trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/repository/user/CartRepository.java
/trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/repository/user/CartRepositoryImpl.java
/trunk/profitmandi-web/src/main/java/com/spice/profitmandi/web/v2/controller/V2BillingController.java
36376 165 d 22 h aman /trunk/ Feat:Cart Api Implementation  
/trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/cart/v2
/trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/cart/v2/BlockerType.java
/trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/cart/v2/CartBlocker.java
/trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/cart/v2/CartContent.java
/trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/cart/v2/CartEventType.java
/trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/cart/v2/CartHydrationService.java
/trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/cart/v2/CartHydrationServiceImpl.java
/trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/cart/v2/CartLifecycleStatus.java
/trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/cart/v2/CartReservationConstants.java
/trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/cart/v2/CartReservationService.java
/trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/cart/v2/CartReservationServiceImpl.java
/trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/cart/v2/CartValidationService.java
/trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/cart/v2/CartValidationServiceImpl.java
/trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/cart/v2/CartWarning.java
/trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/cart/v2/CheckoutValidationResult.java
/trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/cart/v2/CouponState.java
/trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/cart/v2/HydratedCart.java
/trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/cart/v2/HydratedLine.java
/trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/cart/v2/InsuranceBinding.java
/trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/cart/v2/LineReservation.java
/trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/cart/v2/LineStatus.java
/trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/cart/v2/LiveInventory.java
/trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/cart/v2/LivePrice.java
/trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/cart/v2/OpenCartValidationResult.java
/trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/cart/v2/PricingBreakup.java
/trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/cart/v2/Reservation.java
/trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/cart/v2/SaleType.java
/trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/cart/v2/TaxBreakup.java
/trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/cart/v2/WarningType.java
/trunk/profitmandi-web/docs
/trunk/profitmandi-web/docs/tests
/trunk/profitmandi-web/src/main/java/com/spice/profitmandi/web/v2/controller/V2BillingController.java
/trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/entity/user/Cart.java
/trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/entity/user/CartLine.java
/trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/enumuration/dtr/AccountType.java
/trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/repository/dtr/UserAccountRepository.java
/trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/repository/dtr/UserAccountRepositoryImpl.java
/trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/repository/user/CartRepository.java
/trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/repository/user/CartRepositoryImpl.java
/trunk/profitmandi-web/src/main/java/com/spice/profitmandi/web/controller/StoreController.java
/trunk/profitmandi-web/src/main/java/com/spice/profitmandi/web/controller/checkout/OrderController.java
/trunk/profitmandi-web/src/main/java/com/spice/profitmandi/web/v2/controller/V2CartController.java
/trunk/profitmandi-web/src/main/java/com/spice/profitmandi/web/v2/controller/V2OrderController.java
35947 215 d 1 h amit /trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/ Revert r35945: undo cart pessimistic locking (will re-apply after testing)  
/trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/cart/CartService.java
/trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/cart/CartServiceImpl.java
/trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/repository/user/CartRepository.java
/trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/repository/user/CartRepositoryImpl.java
35945 215 d 3 h amit /trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/ Add pessimistic locking to cart operations to prevent deadlocks; add updateCartItem, removeCartItem, getCartItems methods  
/trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/cart/CartService.java
/trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/cart/CartServiceImpl.java
/trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/repository/user/CartRepository.java
/trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/repository/user/CartRepositoryImpl.java
22352 3324 d 1 h ashik.ali /trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/  
/trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/entity/dtr/NotBuyBack.java
/trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/entity/dtr/NotBuyBackId.java
/trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/entity/user/Cart.java
/trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/entity/user/Counter.java
/trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/entity/user/PrivateDealUser.java
/trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/entity/user/PrivateDealUserAddressId.java
/trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/entity/user/PrivateDealUserAddressMapping.java
/trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/entity/user/User.java
/trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/repository/dtr/NotBuyBackRepository.java
/trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/repository/dtr/NotBuyBackRepositoryImpl.java
/trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/repository/user/CartRepository.java
/trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/repository/user/CartRepositoryImpl.java
/trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/repository/user/CounterRepository.java
/trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/repository/user/CounterRepositoryImpl.java
/trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/repository/user/PrivateDealUserAddressMappingRepository.java
/trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/repository/user/PrivateDealUserAddressMappingRepositoryImpl.java
/trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/repository/user/PrivateDealUserRepository.java
/trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/repository/user/PrivateDealUserRepositoryImpl.java
/trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/repository/user/UserRepository.java
/trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/repository/user/UserRepositoryImpl.java
/trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/util/MigrationUtil.java
/trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/util/MongoMigrationUtil.java
/trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/util/UserToRetailerMigrationUtil.java
/trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/entity/dtr/User.java
/trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/entity/dtr/UserAccounts.java
/trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/entity/fofo/InventoryItem.java
/trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/repository/dtr/RetailerRepositoryImpl.java
/trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/repository/dtr/UserAccountImpl.java
/trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/repository/dtr/UserAccountRepository.java
/trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/repository/dtr/UserRepository.java
/trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/repository/dtr/UserRepositoryImpl.java
/trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/repository/fofo/InventoryItemRepositoryImpl.java
/trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/repository/transaction/OrderRepository.java
/trunk/profitmandi-dao/src/main/java/com/spice/profitmandi/dao/repository/transaction/OrderRepositoryImpl.java