generated from pricelees/issue-pr-template
refactor: schedule/hold API에서의 로깅 수정 및 동시성 테스트 추가
This commit is contained in:
parent
10318cab33
commit
a50cbbe43e
@ -71,10 +71,11 @@ class ScheduleService(
|
||||
id = id,
|
||||
currentStatus = ScheduleStatus.AVAILABLE,
|
||||
changeStatus = ScheduleStatus.HOLD
|
||||
)
|
||||
).also {
|
||||
log.info { "[ScheduleService.holdSchedule] $it 개의 row 변경 완료" }
|
||||
}
|
||||
|
||||
if (result == 0) {
|
||||
log.info { "[ScheduleService.holdSchedule] Holding된 일정 없음: id=${id}, count = " }
|
||||
throw ScheduleException(ScheduleErrorCode.SCHEDULE_NOT_AVAILABLE)
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,59 @@
|
||||
package com.sangdol.roomescape.schedule
|
||||
|
||||
import com.sangdol.common.types.web.HttpStatus
|
||||
import com.sangdol.roomescape.schedule.exception.ScheduleErrorCode
|
||||
import com.sangdol.roomescape.schedule.infrastructure.persistence.ScheduleRepository
|
||||
import com.sangdol.roomescape.schedule.infrastructure.persistence.ScheduleStatus
|
||||
import com.sangdol.roomescape.supports.FunSpecSpringbootTest
|
||||
import com.sangdol.roomescape.supports.runTest
|
||||
import io.kotest.assertions.assertSoftly
|
||||
import io.kotest.matchers.collections.shouldContainExactly
|
||||
import io.kotest.matchers.collections.shouldContainExactlyInAnyOrder
|
||||
import io.kotest.matchers.nulls.shouldNotBeNull
|
||||
import io.kotest.matchers.shouldBe
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.awaitAll
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.springframework.data.repository.findByIdOrNull
|
||||
import java.util.concurrent.CountDownLatch
|
||||
|
||||
class ScheduleConcurrencyTest(
|
||||
private val scheduleRepository: ScheduleRepository
|
||||
) : FunSpecSpringbootTest() {
|
||||
init {
|
||||
test("하나의 ${ScheduleStatus.AVAILABLE}인 일정에 대한 동시 HOLD 변경 요청이 들어오면, 가장 먼저 들어온 요청만 성공한다.") {
|
||||
val user = testAuthUtil.defaultUserLogin()
|
||||
val schedule = dummyInitializer.createSchedule()
|
||||
|
||||
withContext(Dispatchers.IO) {
|
||||
val jobSize = 64
|
||||
val latch = CountDownLatch(jobSize)
|
||||
|
||||
(1..jobSize).map {
|
||||
async {
|
||||
latch.countDown()
|
||||
latch.await()
|
||||
|
||||
runTest(
|
||||
token = user.second,
|
||||
on = {
|
||||
post("/schedules/${schedule.id}/hold")
|
||||
},
|
||||
expect = {
|
||||
}
|
||||
).extract().statusCode()
|
||||
}
|
||||
}.awaitAll().also {
|
||||
it.count { statusCode -> statusCode == HttpStatus.OK.value() } shouldBe 1
|
||||
it.count { statusCode -> statusCode == ScheduleErrorCode.SCHEDULE_NOT_AVAILABLE.httpStatus.value() } shouldBe (jobSize - 1)
|
||||
}
|
||||
}
|
||||
|
||||
assertSoftly(scheduleRepository.findByIdOrNull(schedule.id)!!) {
|
||||
this.status shouldBe ScheduleStatus.HOLD
|
||||
this.holdExpiredAt.shouldNotBeNull()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user