Task 1-2: Concurrent Confirm Lock - Rental Order
Phase: 1 Priority: High Module:
application-coreDepends on: Không có Reference: docs/BountyHunter-Backend/details/feature-nft-management/SPEC.md
Background
confirmNftRental(renterId, orderId) không có explicit lock. Race condition: 2 renters gọi đồng thời, cả 2 thấy status=NEW → cả 2 được confirm → double charge cho cả 2 renters.
Tasks
DI Note:
NftRentalOrderServicecần injectLockerService— thêmprivate final LockerService lockerService;và inject qua constructor (dùng@RequiredArgsConstructor).LockerServicelà shared service trongapplication-corehoặccommonmodule — xác nhận package bằng grep:grep -rn "class LockerService". Lock timeout nên ngắn (5-10s) vì operation không lâu — xác nhận signature củalockerService.getInLock()(timeout param có thể optional).
File: application-core/service/nft_rental/nft_rental_order/NftRentalOrderService.java
-
[ ] Inject
LockerServicequa constructor nếu chưa có:@Service @RequiredArgsConstructor public class NftRentalOrderService { private final LockerService lockerService; // thêm vào danh sách inject // ... các dependencies khác } -
[ ] Wrap confirm logic với distributed lock per
orderId:public void confirmNftRental(String renterId, String orderId) { // Lock key pattern: "NFT_RENTAL_CONFIRM_LOCK:{orderId}" lockerService.getInLock( "NFT_RENTAL_CONFIRM_LOCK", orderId, () -> { NftRentalOrderModel order = findById(orderId) .orElseThrow(() -> new BadRequestException(RENTAL_ORDER_NOT_FOUND)); // Guard inside lock: re-check status để tránh TOCTOU race if (order.getRentalStatus() != NftEnum.RentalOrderStatus.NEW) { throw new BadRequestException("RENTAL_ORDER_NOT_AVAILABLE"); } // ... proceed with coin deduction, status update, notification ... } ); } -
[ ] Verify lock timeout: nếu
getInLock()hỗ trợ timeout param → set 5-10s - [ ] Đảm bảo re-check status bên trong lock (double-check locking pattern)
Verification / Acceptance Criteria
- [ ] 2 concurrent
confirm-rent/{orderId}requests → chỉ 1 thành công, 1 nhậnRENTAL_ORDER_NOT_AVAILABLE - [ ] Không có double charge: B-Coin chỉ bị deduct 1 lần
- [ ] Không có double deposit: owner chỉ nhận 1 lần
- [ ] Lock được release sau khi confirm hoàn tất (không deadlock)
- [ ]
RENTAL_ORDER_NOT_FOUNDvẫn trả về đúng khi orderId không tồn tại
Notes
- Lock key pattern:
"NFT_RENTAL_CONFIRM_LOCK" + ":" + orderId - Lock timeout nên ngắn (5-10s) vì operation không lâu
Files to Modify
application-core/service/nft_rental/nft_rental_order/NftRentalOrderService.java