fix(gift): 접수 선물 변경에 쓰기 잠금을 적용한다

This commit is contained in:
2026-10-22 18:22:57 +09:00
parent 45b97088ca
commit 6a9e76c13d
3 changed files with 12 additions and 4 deletions
@@ -4,13 +4,19 @@ import kr.co.vividnext.sodalive.v2.gift.domain.GiftStatus
import org.springframework.data.domain.Page
import org.springframework.data.domain.Pageable
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.repository.query.Param
import java.time.LocalDateTime
import javax.persistence.LockModeType
interface GiftRepository : JpaRepository<Gift, Long> {
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 findByRecipientMemberIdAndStatusIn(
@@ -74,6 +80,7 @@ interface GiftRepository : JpaRepository<Gift, Long> {
)
"""
)
@Lock(LockModeType.PESSIMISTIC_WRITE)
fun findReceivedGiftsWithTrackingDeadlineBefore(@Param("now") now: LocalDateTime): List<Gift>
@Query(
@@ -113,6 +120,7 @@ interface GiftRepository : JpaRepository<Gift, Long> {
)
"""
)
@Lock(LockModeType.PESSIMISTIC_WRITE)
fun findReceivedGiftsWithTrackingDeadlineReminderDue(
@Param("now") now: LocalDateTime,
@Param("reminderUntil") reminderUntil: LocalDateTime
@@ -207,7 +207,7 @@ class GiftCommandService(
@Transactional
fun cancelGift(member: Member, applicationNo: String): GiftCancellationResult {
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()
val canceledAt = now()
@@ -231,7 +231,7 @@ class GiftCommandService(
command: GiftTrackingRegistrationCommand
): GiftTrackingRegistrationResult {
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()
validate(command)
val delivery = deliveryRepository.findByGiftId(gift.id ?: throw invalidRequest()) ?: throw invalidRequest()
@@ -546,7 +546,7 @@ class GiftCommandServiceTest {
senderAddress = "서울시 강남구",
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)
}
@@ -579,7 +579,7 @@ class GiftCommandServiceTest {
senderAddress = "서울시 강남구",
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(
trackingDelivery.takeIf { deliveryExists }
)