fix(gift): 접수 선물 변경에 쓰기 잠금을 적용한다
This commit is contained in:
+8
@@ -4,13 +4,19 @@ import kr.co.vividnext.sodalive.v2.gift.domain.GiftStatus
|
|||||||
import org.springframework.data.domain.Page
|
import org.springframework.data.domain.Page
|
||||||
import org.springframework.data.domain.Pageable
|
import org.springframework.data.domain.Pageable
|
||||||
import org.springframework.data.jpa.repository.JpaRepository
|
import org.springframework.data.jpa.repository.JpaRepository
|
||||||
|
import org.springframework.data.jpa.repository.Lock
|
||||||
import org.springframework.data.jpa.repository.Query
|
import org.springframework.data.jpa.repository.Query
|
||||||
import org.springframework.data.repository.query.Param
|
import org.springframework.data.repository.query.Param
|
||||||
import java.time.LocalDateTime
|
import java.time.LocalDateTime
|
||||||
|
import javax.persistence.LockModeType
|
||||||
|
|
||||||
interface GiftRepository : JpaRepository<Gift, Long> {
|
interface GiftRepository : JpaRepository<Gift, Long> {
|
||||||
fun findByApplicationNo(applicationNo: String): Gift?
|
fun findByApplicationNo(applicationNo: String): Gift?
|
||||||
|
|
||||||
|
@Lock(LockModeType.PESSIMISTIC_WRITE)
|
||||||
|
@Query("select g from Gift g where g.applicationNo = :applicationNo")
|
||||||
|
fun findByApplicationNoForUpdate(@Param("applicationNo") applicationNo: String): Gift?
|
||||||
|
|
||||||
fun findBySenderMemberId(senderMemberId: Long, pageable: Pageable): Page<Gift>
|
fun findBySenderMemberId(senderMemberId: Long, pageable: Pageable): Page<Gift>
|
||||||
|
|
||||||
fun findByRecipientMemberIdAndStatusIn(
|
fun findByRecipientMemberIdAndStatusIn(
|
||||||
@@ -74,6 +80,7 @@ interface GiftRepository : JpaRepository<Gift, Long> {
|
|||||||
)
|
)
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
|
@Lock(LockModeType.PESSIMISTIC_WRITE)
|
||||||
fun findReceivedGiftsWithTrackingDeadlineBefore(@Param("now") now: LocalDateTime): List<Gift>
|
fun findReceivedGiftsWithTrackingDeadlineBefore(@Param("now") now: LocalDateTime): List<Gift>
|
||||||
|
|
||||||
@Query(
|
@Query(
|
||||||
@@ -113,6 +120,7 @@ interface GiftRepository : JpaRepository<Gift, Long> {
|
|||||||
)
|
)
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
|
@Lock(LockModeType.PESSIMISTIC_WRITE)
|
||||||
fun findReceivedGiftsWithTrackingDeadlineReminderDue(
|
fun findReceivedGiftsWithTrackingDeadlineReminderDue(
|
||||||
@Param("now") now: LocalDateTime,
|
@Param("now") now: LocalDateTime,
|
||||||
@Param("reminderUntil") reminderUntil: LocalDateTime
|
@Param("reminderUntil") reminderUntil: LocalDateTime
|
||||||
|
|||||||
@@ -207,7 +207,7 @@ class GiftCommandService(
|
|||||||
@Transactional
|
@Transactional
|
||||||
fun cancelGift(member: Member, applicationNo: String): GiftCancellationResult {
|
fun cancelGift(member: Member, applicationNo: String): GiftCancellationResult {
|
||||||
val senderMemberId = member.id ?: throw invalidRequest()
|
val senderMemberId = member.id ?: throw invalidRequest()
|
||||||
val gift = giftRepository.findByApplicationNo(applicationNo) ?: throw invalidRequest()
|
val gift = giftRepository.findByApplicationNoForUpdate(applicationNo) ?: throw invalidRequest()
|
||||||
if (gift.senderMemberId != senderMemberId || gift.status != GiftStatus.RECEIVED) throw invalidRequest()
|
if (gift.senderMemberId != senderMemberId || gift.status != GiftStatus.RECEIVED) throw invalidRequest()
|
||||||
|
|
||||||
val canceledAt = now()
|
val canceledAt = now()
|
||||||
@@ -231,7 +231,7 @@ class GiftCommandService(
|
|||||||
command: GiftTrackingRegistrationCommand
|
command: GiftTrackingRegistrationCommand
|
||||||
): GiftTrackingRegistrationResult {
|
): GiftTrackingRegistrationResult {
|
||||||
val senderMemberId = member.id ?: throw invalidRequest()
|
val senderMemberId = member.id ?: throw invalidRequest()
|
||||||
val gift = giftRepository.findByApplicationNo(applicationNo) ?: throw invalidRequest()
|
val gift = giftRepository.findByApplicationNoForUpdate(applicationNo) ?: throw invalidRequest()
|
||||||
if (gift.senderMemberId != senderMemberId || gift.status != GiftStatus.RECEIVED) throw invalidRequest()
|
if (gift.senderMemberId != senderMemberId || gift.status != GiftStatus.RECEIVED) throw invalidRequest()
|
||||||
validate(command)
|
validate(command)
|
||||||
val delivery = deliveryRepository.findByGiftId(gift.id ?: throw invalidRequest()) ?: throw invalidRequest()
|
val delivery = deliveryRepository.findByGiftId(gift.id ?: throw invalidRequest()) ?: throw invalidRequest()
|
||||||
|
|||||||
@@ -546,7 +546,7 @@ class GiftCommandServiceTest {
|
|||||||
senderAddress = "서울시 강남구",
|
senderAddress = "서울시 강남구",
|
||||||
trackingDeadlineAt = NOW.plusDays(3)
|
trackingDeadlineAt = NOW.plusDays(3)
|
||||||
)
|
)
|
||||||
Mockito.`when`(giftRepository.findByApplicationNo(APPLICATION_NO)).thenReturn(cancellationGift)
|
Mockito.`when`(giftRepository.findByApplicationNoForUpdate(APPLICATION_NO)).thenReturn(cancellationGift)
|
||||||
Mockito.`when`(deliveryRepository.findByGiftId(GIFT_ID)).thenReturn(cancellationDelivery)
|
Mockito.`when`(deliveryRepository.findByGiftId(GIFT_ID)).thenReturn(cancellationDelivery)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -579,7 +579,7 @@ class GiftCommandServiceTest {
|
|||||||
senderAddress = "서울시 강남구",
|
senderAddress = "서울시 강남구",
|
||||||
trackingDeadlineAt = NOW.plusDays(3)
|
trackingDeadlineAt = NOW.plusDays(3)
|
||||||
)
|
)
|
||||||
Mockito.`when`(giftRepository.findByApplicationNo(APPLICATION_NO)).thenReturn(trackingGift)
|
Mockito.`when`(giftRepository.findByApplicationNoForUpdate(APPLICATION_NO)).thenReturn(trackingGift)
|
||||||
Mockito.`when`(deliveryRepository.findByGiftId(GIFT_ID)).thenReturn(
|
Mockito.`when`(deliveryRepository.findByGiftId(GIFT_ID)).thenReturn(
|
||||||
trackingDelivery.takeIf { deliveryExists }
|
trackingDelivery.takeIf { deliveryExists }
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user