generated from pricelees/issue-pr-template
refactor: 일정 HOLD 로직 수정
- 충돌 방지를 위해 조회시 Lock 추가 - 해당 일정의 시작 시간이 현재 시간 이후인지 검증 로직 추가
This commit is contained in:
parent
1c700130c4
commit
44c556776d
@ -71,19 +71,18 @@ class ScheduleService(
|
|||||||
@Transactional
|
@Transactional
|
||||||
fun holdSchedule(id: Long) {
|
fun holdSchedule(id: Long) {
|
||||||
log.info { "[holdSchedule] 일정 Holding 시작: id=$id" }
|
log.info { "[holdSchedule] 일정 Holding 시작: id=$id" }
|
||||||
val result: Int = scheduleRepository.changeStatus(
|
|
||||||
id = id,
|
val schedule = findForUpdateOrThrow(id).also {
|
||||||
currentStatus = ScheduleStatus.AVAILABLE,
|
scheduleValidator.validateCanHold(it)
|
||||||
|
}
|
||||||
|
|
||||||
|
scheduleRepository.changeStatus(
|
||||||
|
id = schedule.id,
|
||||||
|
currentStatus = schedule.status,
|
||||||
changeStatus = ScheduleStatus.HOLD
|
changeStatus = ScheduleStatus.HOLD
|
||||||
).also {
|
).also {
|
||||||
log.info { "[holdSchedule] $it 개의 row 변경 완료" }
|
log.info { "[holdSchedule] 일정 Holding 완료: id=$id" }
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result == 0) {
|
|
||||||
throw ScheduleException(ScheduleErrorCode.SCHEDULE_NOT_AVAILABLE)
|
|
||||||
}
|
|
||||||
|
|
||||||
log.info { "[holdSchedule] 일정 Holding 완료: id=$id" }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ========================================
|
// ========================================
|
||||||
@ -222,7 +221,18 @@ class ScheduleService(
|
|||||||
return scheduleRepository.findByIdOrNull(id)
|
return scheduleRepository.findByIdOrNull(id)
|
||||||
?.also { log.info { "[findOrThrow] 일정 조회 완료: id=$id" } }
|
?.also { log.info { "[findOrThrow] 일정 조회 완료: id=$id" } }
|
||||||
?: run {
|
?: run {
|
||||||
log.warn { "[updateSchedule] 일정 조회 실패. id=$id" }
|
log.warn { "[findOrThrow] 일정 조회 실패. id=$id" }
|
||||||
|
throw ScheduleException(ScheduleErrorCode.SCHEDULE_NOT_FOUND)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun findForUpdateOrThrow(id: Long): ScheduleEntity {
|
||||||
|
log.info { "[findForUpdateOrThrow] 일정 LOCK + 조회 시작: id=$id" }
|
||||||
|
|
||||||
|
return scheduleRepository.findByIdForUpdate(id)
|
||||||
|
?.also { log.info { "[findForUpdateOrThrow] 일정 조회 완료: id=$id" } }
|
||||||
|
?: run {
|
||||||
|
log.warn { "[findForUpdateOrThrow] 일정 조회 실패. id=$id" }
|
||||||
throw ScheduleException(ScheduleErrorCode.SCHEDULE_NOT_FOUND)
|
throw ScheduleException(ScheduleErrorCode.SCHEDULE_NOT_FOUND)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -22,6 +22,15 @@ private val log: KLogger = KotlinLogging.logger {}
|
|||||||
class ScheduleValidator(
|
class ScheduleValidator(
|
||||||
private val scheduleRepository: ScheduleRepository
|
private val scheduleRepository: ScheduleRepository
|
||||||
) {
|
) {
|
||||||
|
fun validateCanHold(schedule: ScheduleEntity) {
|
||||||
|
if (schedule.status != ScheduleStatus.AVAILABLE) {
|
||||||
|
log.info { "[validateCanHold] HOLD 실패: id=${schedule.id}, status=${schedule.status}" }
|
||||||
|
throw ScheduleException(ScheduleErrorCode.SCHEDULE_NOT_AVAILABLE)
|
||||||
|
}
|
||||||
|
|
||||||
|
validateNotInPast(schedule.date, schedule.time)
|
||||||
|
}
|
||||||
|
|
||||||
fun validateCanDelete(schedule: ScheduleEntity) {
|
fun validateCanDelete(schedule: ScheduleEntity) {
|
||||||
val status: ScheduleStatus = schedule.status
|
val status: ScheduleStatus = schedule.status
|
||||||
|
|
||||||
|
|||||||
@ -155,12 +155,28 @@ class ScheduleApiTest(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test("해당 일정의 시작 시간이 현재 시간 이전이면 실패한다.") {
|
||||||
|
val schedule = dummyInitializer.createSchedule(
|
||||||
|
request = ScheduleFixture.createRequest.copy(
|
||||||
|
date = KoreaDate.today(),
|
||||||
|
time = KoreaTime.now().minusMinutes(1)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
runExceptionTest(
|
||||||
|
token = testAuthUtil.defaultUserLogin().second,
|
||||||
|
method = HttpMethod.POST,
|
||||||
|
endpoint = "/schedules/${schedule.id}/hold",
|
||||||
|
expectedErrorCode = ScheduleErrorCode.PAST_DATE_TIME
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
test("일정이 없으면 실패한다.") {
|
test("일정이 없으면 실패한다.") {
|
||||||
runExceptionTest(
|
runExceptionTest(
|
||||||
token = testAuthUtil.defaultUserLogin().second,
|
token = testAuthUtil.defaultUserLogin().second,
|
||||||
method = HttpMethod.POST,
|
method = HttpMethod.POST,
|
||||||
endpoint = "/schedules/${INVALID_PK}/hold",
|
endpoint = "/schedules/${INVALID_PK}/hold",
|
||||||
expectedErrorCode = ScheduleErrorCode.SCHEDULE_NOT_AVAILABLE
|
expectedErrorCode = ScheduleErrorCode.SCHEDULE_NOT_FOUND
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user