From 519ccafb86b98f1ea01420a6c4bd258d78d91191 Mon Sep 17 00:00:00 2001 From: "Jaemin.Park" Date: Sat, 29 Jul 2023 16:13:53 +0900 Subject: [PATCH 1/8] Implement adjusting absence status api --- .../moit/controller/study/StudyController.kt | 13 +++++++++++-- .../mashup/moit/controller/study/dto/StudyDto.kt | 7 +++++++ .../kotlin/com/mashup/moit/facade/StudyFacade.kt | 14 ++++++++++++++ .../moit/domain/attendance/AttendanceRepository.kt | 1 + .../moit/domain/attendance/AttendanceService.kt | 7 +++++++ .../com/mashup/moit/domain/study/StudyEntity.kt | 3 +++ .../mashup/moit/domain/study/StudyRepository.kt | 1 + .../com/mashup/moit/domain/study/StudyService.kt | 5 +++++ 8 files changed, 49 insertions(+), 2 deletions(-) diff --git a/moit-api/src/main/kotlin/com/mashup/moit/controller/study/StudyController.kt b/moit-api/src/main/kotlin/com/mashup/moit/controller/study/StudyController.kt index 9fe40702..6dfbc175 100644 --- a/moit-api/src/main/kotlin/com/mashup/moit/controller/study/StudyController.kt +++ b/moit-api/src/main/kotlin/com/mashup/moit/controller/study/StudyController.kt @@ -1,14 +1,15 @@ package com.mashup.moit.controller.study import com.mashup.moit.common.MoitApiResponse -import com.mashup.moit.security.authentication.UserInfo -import com.mashup.moit.security.resolver.GetAuth +import com.mashup.moit.controller.study.dto.StudyAdjustAbsenceRequest import com.mashup.moit.controller.study.dto.StudyAttendanceKeywordRequest import com.mashup.moit.controller.study.dto.StudyAttendanceKeywordResponse import com.mashup.moit.controller.study.dto.StudyDetailsResponse import com.mashup.moit.controller.study.dto.StudyFirstAttendanceResponse import com.mashup.moit.controller.study.dto.StudyUserAttendanceStatusResponse import com.mashup.moit.facade.StudyFacade +import com.mashup.moit.security.authentication.UserInfo +import com.mashup.moit.security.resolver.GetAuth import io.swagger.v3.oas.annotations.Operation import io.swagger.v3.oas.annotations.tags.Tag import jakarta.validation.Valid @@ -78,4 +79,12 @@ class StudyController( studyFacade.initializeAttendance(studyId) return MoitApiResponse.success() } + + @Operation(summary = "Adjust Absence Status", description = "Study 결석 처리") + @PostMapping("/attendance/adjust/absence") + fun adjustAbsenceStatus(@RequestBody request: StudyAdjustAbsenceRequest): MoitApiResponse { + studyFacade.adjustAbsenceStatus(request.studyIds.toSet()) + return MoitApiResponse.success() + + } } diff --git a/moit-api/src/main/kotlin/com/mashup/moit/controller/study/dto/StudyDto.kt b/moit-api/src/main/kotlin/com/mashup/moit/controller/study/dto/StudyDto.kt index 30819ab9..61eee3d5 100644 --- a/moit-api/src/main/kotlin/com/mashup/moit/controller/study/dto/StudyDto.kt +++ b/moit-api/src/main/kotlin/com/mashup/moit/controller/study/dto/StudyDto.kt @@ -93,3 +93,10 @@ data class StudyUserAttendanceStatusResponse( ) } } + +@Schema(description = "Study 결석 처리 요청") +data class StudyAdjustAbsenceRequest( + @Schema(description = "Study Ids") + @field:NotBlank + val studyIds: List +) diff --git a/moit-api/src/main/kotlin/com/mashup/moit/facade/StudyFacade.kt b/moit-api/src/main/kotlin/com/mashup/moit/facade/StudyFacade.kt index ce2efb05..56e5fc59 100644 --- a/moit-api/src/main/kotlin/com/mashup/moit/facade/StudyFacade.kt +++ b/moit-api/src/main/kotlin/com/mashup/moit/facade/StudyFacade.kt @@ -6,6 +6,7 @@ import com.mashup.moit.controller.study.dto.StudyDetailsResponse import com.mashup.moit.controller.study.dto.StudyFirstAttendanceResponse import com.mashup.moit.controller.study.dto.StudyUserAttendanceStatusResponse import com.mashup.moit.domain.attendance.AttendanceService +import com.mashup.moit.domain.fine.FineService import com.mashup.moit.domain.moit.MoitService import com.mashup.moit.domain.study.StudyService import com.mashup.moit.domain.user.UserService @@ -20,6 +21,7 @@ class StudyFacade( private val moitService: MoitService, private val studyService: StudyService, private val attendanceService: AttendanceService, + private val fineService: FineService, private val userService: UserService, private val eventProducer: EventProducer ) { @@ -69,4 +71,16 @@ class StudyFacade( fun checkFirstAttendance(studyId: Long): StudyFirstAttendanceResponse { return StudyFirstAttendanceResponse.of(attendanceService.existFirstAttendanceByStudyId(studyId)) } + + @Transactional + fun adjustAbsenceStatus(studyIds: Set) { + studyService.findByStudyIds(studyIds.toList()) + .groupBy { study -> study.moitId } + .forEach { (moitId, studies) -> + studies.forEach { study -> + attendanceService.adjustUndecidedAttendancesByStudyId(study.id) + .forEach { attendanceId -> fineService.create(attendanceId, moitId) } + } + } + } } diff --git a/moit-domain/src/main/kotlin/com/mashup/moit/domain/attendance/AttendanceRepository.kt b/moit-domain/src/main/kotlin/com/mashup/moit/domain/attendance/AttendanceRepository.kt index 9aa75c66..58b420bc 100644 --- a/moit-domain/src/main/kotlin/com/mashup/moit/domain/attendance/AttendanceRepository.kt +++ b/moit-domain/src/main/kotlin/com/mashup/moit/domain/attendance/AttendanceRepository.kt @@ -7,5 +7,6 @@ import org.springframework.stereotype.Repository interface AttendanceRepository : JpaRepository { fun findByUserIdAndStudyId(userId: Long, studyId: Long): AttendanceEntity? fun findAllByStudyIdOrderByAttendanceAtAsc(studyId: Long): List + fun findAllByStudyIdAndStatus(studyId: Long, status: AttendanceStatus): List fun existsByStudyIdAndStatus(studyId: Long, status: AttendanceStatus): Boolean } diff --git a/moit-domain/src/main/kotlin/com/mashup/moit/domain/attendance/AttendanceService.kt b/moit-domain/src/main/kotlin/com/mashup/moit/domain/attendance/AttendanceService.kt index 21f07b99..236ae8f9 100644 --- a/moit-domain/src/main/kotlin/com/mashup/moit/domain/attendance/AttendanceService.kt +++ b/moit-domain/src/main/kotlin/com/mashup/moit/domain/attendance/AttendanceService.kt @@ -59,4 +59,11 @@ class AttendanceService( fun existFirstAttendanceByStudyId(studyId: Long): Boolean { return attendanceRepository.existsByStudyIdAndStatus(studyId, AttendanceStatus.ATTENDANCE) } + + @Transactional + fun adjustUndecidedAttendancesByStudyId(studyId: Long, status: AttendanceStatus = AttendanceStatus.ABSENCE): List { + val attendances = attendanceRepository.findAllByStudyIdAndStatus(studyId, AttendanceStatus.UNDECIDED) + attendances.forEach { attendance -> attendance.status = status } + return attendances.map { it.id } + } } diff --git a/moit-domain/src/main/kotlin/com/mashup/moit/domain/study/StudyEntity.kt b/moit-domain/src/main/kotlin/com/mashup/moit/domain/study/StudyEntity.kt index dc3f3175..43f144a4 100644 --- a/moit-domain/src/main/kotlin/com/mashup/moit/domain/study/StudyEntity.kt +++ b/moit-domain/src/main/kotlin/com/mashup/moit/domain/study/StudyEntity.kt @@ -40,6 +40,9 @@ class StudyEntity( @Column(name = "is_initialized", nullable = false) var isInitialized: Boolean = false + @Column(name = "is_finalized", nullable = false) + var isFinalized: Boolean = false + fun toDomain() = Study( id = id, moitId = moitId, diff --git a/moit-domain/src/main/kotlin/com/mashup/moit/domain/study/StudyRepository.kt b/moit-domain/src/main/kotlin/com/mashup/moit/domain/study/StudyRepository.kt index 550e01e5..efe15b21 100644 --- a/moit-domain/src/main/kotlin/com/mashup/moit/domain/study/StudyRepository.kt +++ b/moit-domain/src/main/kotlin/com/mashup/moit/domain/study/StudyRepository.kt @@ -10,6 +10,7 @@ interface StudyRepository : JpaRepository { // findAll By StartAtBefore And IsInitializedFalse fun findAllByStartAtBeforeAndIsInitializedFalse(startAt: LocalDateTime): List fun findAllByMoitIdAndStartAtBeforeOrderByOrderDesc(moitId: Long, startAt: LocalDateTime): List + fun findAllByEndAtBeforeAndIsFinalizedFalse(endAt: LocalDateTime): List // findAll By minDt <= StartAt <= maxDt (cause: Between Index performance degradation) fun findAllByStartAtGreaterThanEqualAndStartAtLessThanEqual(minStartAt: LocalDateTime, maxStartAt: LocalDateTime): List diff --git a/moit-domain/src/main/kotlin/com/mashup/moit/domain/study/StudyService.kt b/moit-domain/src/main/kotlin/com/mashup/moit/domain/study/StudyService.kt index 91fbbbee..7c200365 100644 --- a/moit-domain/src/main/kotlin/com/mashup/moit/domain/study/StudyService.kt +++ b/moit-domain/src/main/kotlin/com/mashup/moit/domain/study/StudyService.kt @@ -113,4 +113,9 @@ class StudyService( .filter { !it.isInitialized } // 모종의 initialize 실패 인입 방지 .map { it.toDomain() } } + + fun findUnfinalizedStudiesByEndAt(endAt: LocalDateTime): List { + return studyRepository.findAllByEndAtBeforeAndIsFinalizedFalse(endAt) + .map { it.toDomain() } + } } From 8800267c2cd0c994b1d74a2689379167a27e3037 Mon Sep 17 00:00:00 2001 From: "Jaemin.Park" Date: Sat, 29 Jul 2023 16:14:05 +0900 Subject: [PATCH 2/8] Implement adjusting absence scheduler --- .../com/mashup/moit/config/AsyncConfig.kt | 11 ++++++ .../scheduler/StudyAdjustAbsenceScheduler.kt | 39 +++++++++++++++++++ 2 files changed, 50 insertions(+) create mode 100644 moit-api/src/main/kotlin/com/mashup/moit/scheduler/StudyAdjustAbsenceScheduler.kt diff --git a/moit-api/src/main/kotlin/com/mashup/moit/config/AsyncConfig.kt b/moit-api/src/main/kotlin/com/mashup/moit/config/AsyncConfig.kt index 0737fe97..ba330ddd 100644 --- a/moit-api/src/main/kotlin/com/mashup/moit/config/AsyncConfig.kt +++ b/moit-api/src/main/kotlin/com/mashup/moit/config/AsyncConfig.kt @@ -30,4 +30,15 @@ class AsyncConfig { setWaitForTasksToCompleteOnShutdown(true) } } + + @Bean(name = ["absenceSchedulerExecutor"]) + fun absenceSchedulerExecutor(): Executor { + return ThreadPoolTaskExecutor().apply { + corePoolSize = 5 + maxPoolSize = 5 + queueCapacity = 20 + setThreadNamePrefix("AbsenceSchedulerThread-") + setWaitForTasksToCompleteOnShutdown(true) + } + } } diff --git a/moit-api/src/main/kotlin/com/mashup/moit/scheduler/StudyAdjustAbsenceScheduler.kt b/moit-api/src/main/kotlin/com/mashup/moit/scheduler/StudyAdjustAbsenceScheduler.kt new file mode 100644 index 00000000..6e80d711 --- /dev/null +++ b/moit-api/src/main/kotlin/com/mashup/moit/scheduler/StudyAdjustAbsenceScheduler.kt @@ -0,0 +1,39 @@ +package com.mashup.moit.scheduler + +import com.mashup.moit.domain.attendance.AttendanceService +import com.mashup.moit.domain.fine.FineService +import com.mashup.moit.domain.study.StudyService +import org.springframework.scheduling.annotation.Async +import org.springframework.scheduling.annotation.Scheduled +import org.springframework.stereotype.Component +import org.springframework.transaction.annotation.Transactional +import java.time.LocalDateTime + +@Component +class StudyAdjustAbsenceScheduler( + private val studyService: StudyService, + private val attendanceService: AttendanceService, + private val fineService: FineService +) { + + @Scheduled(cron = "0 */5 * * * *") + @Async("asyncSchedulerExecutor") + @Transactional + fun adjustAbsenceStatusFromNow() { + // 결석 확정을 지을 때 endAt을 현재 시간보다 15초 정도 유예기간을 줌. 5분마다 배치가 돌기 때문에 95% 시간 내에 끝난 스터디를 반환함 + val undecided = studyService.findUnfinalizedStudiesByEndAt(LocalDateTime.now().minusSeconds(DECIDE_ABSENCE_RANGE)) + .map { it.id } + studyService.findByStudyIds(undecided) + .groupBy { study -> study.moitId } + .forEach { (moitId, studies) -> + studies.forEach { study -> + attendanceService.adjustUndecidedAttendancesByStudyId(study.id) + .forEach { attendanceId -> fineService.create(attendanceId, moitId) } + } + } + } + + companion object { + private const val DECIDE_ABSENCE_RANGE = 15L + } +} From eaf2112577c6f704e71eca7bf372b8b1be716ed5 Mon Sep 17 00:00:00 2001 From: "Jaemin.Park" Date: Sat, 29 Jul 2023 17:37:27 +0900 Subject: [PATCH 3/8] Remove unnecessary thread executor --- .../main/kotlin/com/mashup/moit/config/AsyncConfig.kt | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/moit-api/src/main/kotlin/com/mashup/moit/config/AsyncConfig.kt b/moit-api/src/main/kotlin/com/mashup/moit/config/AsyncConfig.kt index ba330ddd..0737fe97 100644 --- a/moit-api/src/main/kotlin/com/mashup/moit/config/AsyncConfig.kt +++ b/moit-api/src/main/kotlin/com/mashup/moit/config/AsyncConfig.kt @@ -30,15 +30,4 @@ class AsyncConfig { setWaitForTasksToCompleteOnShutdown(true) } } - - @Bean(name = ["absenceSchedulerExecutor"]) - fun absenceSchedulerExecutor(): Executor { - return ThreadPoolTaskExecutor().apply { - corePoolSize = 5 - maxPoolSize = 5 - queueCapacity = 20 - setThreadNamePrefix("AbsenceSchedulerThread-") - setWaitForTasksToCompleteOnShutdown(true) - } - } } From 0791ee9dc9e74728fe08dd34e0eb1b5f2f2ff70f Mon Sep 17 00:00:00 2001 From: "Jaemin.Park" Date: Sat, 29 Jul 2023 17:38:21 +0900 Subject: [PATCH 4/8] Add leaving logs when scheduler started --- .../moit/scheduler/StudyAdjustAbsenceScheduler.kt | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/moit-api/src/main/kotlin/com/mashup/moit/scheduler/StudyAdjustAbsenceScheduler.kt b/moit-api/src/main/kotlin/com/mashup/moit/scheduler/StudyAdjustAbsenceScheduler.kt index 6e80d711..b75f87dd 100644 --- a/moit-api/src/main/kotlin/com/mashup/moit/scheduler/StudyAdjustAbsenceScheduler.kt +++ b/moit-api/src/main/kotlin/com/mashup/moit/scheduler/StudyAdjustAbsenceScheduler.kt @@ -3,6 +3,8 @@ package com.mashup.moit.scheduler import com.mashup.moit.domain.attendance.AttendanceService import com.mashup.moit.domain.fine.FineService import com.mashup.moit.domain.study.StudyService +import org.slf4j.Logger +import org.slf4j.LoggerFactory import org.springframework.scheduling.annotation.Async import org.springframework.scheduling.annotation.Scheduled import org.springframework.stereotype.Component @@ -15,14 +17,19 @@ class StudyAdjustAbsenceScheduler( private val attendanceService: AttendanceService, private val fineService: FineService ) { + val logger: Logger = LoggerFactory.getLogger(StudyAdjustAbsenceScheduler::class.java) @Scheduled(cron = "0 */5 * * * *") @Async("asyncSchedulerExecutor") @Transactional fun adjustAbsenceStatusFromNow() { // 결석 확정을 지을 때 endAt을 현재 시간보다 15초 정도 유예기간을 줌. 5분마다 배치가 돌기 때문에 95% 시간 내에 끝난 스터디를 반환함 - val undecided = studyService.findUnfinalizedStudiesByEndAt(LocalDateTime.now().minusSeconds(DECIDE_ABSENCE_RANGE)) + val scheduleContext = LocalDateTime.now() + val undecided = studyService + .findUnfinalizedStudiesByEndAt(LocalDateTime.now().minusSeconds(DECIDE_ABSENCE_RANGE_SECONDS)) .map { it.id } + logger.info("{} undecided studies start! Start adjusting absence status at {}.", undecided.size, scheduleContext) + studyService.findByStudyIds(undecided) .groupBy { study -> study.moitId } .forEach { (moitId, studies) -> @@ -31,9 +38,11 @@ class StudyAdjustAbsenceScheduler( .forEach { attendanceId -> fineService.create(attendanceId, moitId) } } } + + logger.info("Done adjusting absence status for {} studies, at {}", undecided.size, LocalDateTime.now()) } companion object { - private const val DECIDE_ABSENCE_RANGE = 15L + private const val DECIDE_ABSENCE_RANGE_SECONDS = 15L } } From 092a967897b1f78ea003065efc2705ff705d9b19 Mon Sep 17 00:00:00 2001 From: "Jaemin.Park" Date: Sat, 29 Jul 2023 18:52:46 +0900 Subject: [PATCH 5/8] Cleanup codes --- .../kotlin/com/mashup/moit/facade/StudyFacade.kt | 12 ++++-------- .../moit/scheduler/StudyAdjustAbsenceScheduler.kt | 2 +- .../com/mashup/moit/domain/study/StudyService.kt | 2 +- 3 files changed, 6 insertions(+), 10 deletions(-) diff --git a/moit-api/src/main/kotlin/com/mashup/moit/facade/StudyFacade.kt b/moit-api/src/main/kotlin/com/mashup/moit/facade/StudyFacade.kt index 56e5fc59..41500c98 100644 --- a/moit-api/src/main/kotlin/com/mashup/moit/facade/StudyFacade.kt +++ b/moit-api/src/main/kotlin/com/mashup/moit/facade/StudyFacade.kt @@ -74,13 +74,9 @@ class StudyFacade( @Transactional fun adjustAbsenceStatus(studyIds: Set) { - studyService.findByStudyIds(studyIds.toList()) - .groupBy { study -> study.moitId } - .forEach { (moitId, studies) -> - studies.forEach { study -> - attendanceService.adjustUndecidedAttendancesByStudyId(study.id) - .forEach { attendanceId -> fineService.create(attendanceId, moitId) } - } - } + studyService.findByStudyIds(studyIds.toList()).forEach { study -> + attendanceService.adjustUndecidedAttendancesByStudyId(study.id) + .forEach { attendanceId -> fineService.create(attendanceId, study.moitId) } + } } } diff --git a/moit-api/src/main/kotlin/com/mashup/moit/scheduler/StudyAdjustAbsenceScheduler.kt b/moit-api/src/main/kotlin/com/mashup/moit/scheduler/StudyAdjustAbsenceScheduler.kt index b75f87dd..c8052482 100644 --- a/moit-api/src/main/kotlin/com/mashup/moit/scheduler/StudyAdjustAbsenceScheduler.kt +++ b/moit-api/src/main/kotlin/com/mashup/moit/scheduler/StudyAdjustAbsenceScheduler.kt @@ -26,7 +26,7 @@ class StudyAdjustAbsenceScheduler( // 결석 확정을 지을 때 endAt을 현재 시간보다 15초 정도 유예기간을 줌. 5분마다 배치가 돌기 때문에 95% 시간 내에 끝난 스터디를 반환함 val scheduleContext = LocalDateTime.now() val undecided = studyService - .findUnfinalizedStudiesByEndAt(LocalDateTime.now().minusSeconds(DECIDE_ABSENCE_RANGE_SECONDS)) + .findUnfinalizedStudiesByEndAtBefore(LocalDateTime.now().minusSeconds(DECIDE_ABSENCE_RANGE_SECONDS)) .map { it.id } logger.info("{} undecided studies start! Start adjusting absence status at {}.", undecided.size, scheduleContext) diff --git a/moit-domain/src/main/kotlin/com/mashup/moit/domain/study/StudyService.kt b/moit-domain/src/main/kotlin/com/mashup/moit/domain/study/StudyService.kt index 7c200365..f2b96e7e 100644 --- a/moit-domain/src/main/kotlin/com/mashup/moit/domain/study/StudyService.kt +++ b/moit-domain/src/main/kotlin/com/mashup/moit/domain/study/StudyService.kt @@ -114,7 +114,7 @@ class StudyService( .map { it.toDomain() } } - fun findUnfinalizedStudiesByEndAt(endAt: LocalDateTime): List { + fun findUnfinalizedStudiesByEndAtBefore(endAt: LocalDateTime): List { return studyRepository.findAllByEndAtBeforeAndIsFinalizedFalse(endAt) .map { it.toDomain() } } From 7fe715dfe932932850442471b1c743f72075ae9b Mon Sep 17 00:00:00 2001 From: "Jaemin.Park" Date: Sat, 29 Jul 2023 20:14:12 +0900 Subject: [PATCH 6/8] Update adjusting absence status batch logic --- .../moit/scheduler/StudyAdjustAbsenceScheduler.kt | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/moit-api/src/main/kotlin/com/mashup/moit/scheduler/StudyAdjustAbsenceScheduler.kt b/moit-api/src/main/kotlin/com/mashup/moit/scheduler/StudyAdjustAbsenceScheduler.kt index c8052482..46a3fac7 100644 --- a/moit-api/src/main/kotlin/com/mashup/moit/scheduler/StudyAdjustAbsenceScheduler.kt +++ b/moit-api/src/main/kotlin/com/mashup/moit/scheduler/StudyAdjustAbsenceScheduler.kt @@ -3,6 +3,8 @@ package com.mashup.moit.scheduler import com.mashup.moit.domain.attendance.AttendanceService import com.mashup.moit.domain.fine.FineService import com.mashup.moit.domain.study.StudyService +import com.mashup.moit.infra.event.EventProducer +import com.mashup.moit.infra.event.StudyAttendanceEvent import org.slf4j.Logger import org.slf4j.LoggerFactory import org.springframework.scheduling.annotation.Async @@ -15,7 +17,7 @@ import java.time.LocalDateTime class StudyAdjustAbsenceScheduler( private val studyService: StudyService, private val attendanceService: AttendanceService, - private val fineService: FineService + private val eventProducer: EventProducer ) { val logger: Logger = LoggerFactory.getLogger(StudyAdjustAbsenceScheduler::class.java) @@ -31,12 +33,11 @@ class StudyAdjustAbsenceScheduler( logger.info("{} undecided studies start! Start adjusting absence status at {}.", undecided.size, scheduleContext) studyService.findByStudyIds(undecided) - .groupBy { study -> study.moitId } - .forEach { (moitId, studies) -> - studies.forEach { study -> - attendanceService.adjustUndecidedAttendancesByStudyId(study.id) - .forEach { attendanceId -> fineService.create(attendanceId, moitId) } - } + .forEach { study -> + attendanceService.adjustUndecidedAttendancesByStudyId(study.id) + .forEach { attendanceId -> + eventProducer.produce(StudyAttendanceEvent(attendanceId = attendanceId, moitId = study.moitId)) + } } logger.info("Done adjusting absence status for {} studies, at {}", undecided.size, LocalDateTime.now()) From 5bfd4c85088d5e4ebc94100b270afabbe5d3a32a Mon Sep 17 00:00:00 2001 From: "Jaemin.Park" Date: Sat, 29 Jul 2023 21:58:21 +0900 Subject: [PATCH 7/8] Refactor codes --- .../scheduler/StudyAdjustAbsenceScheduler.kt | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/moit-api/src/main/kotlin/com/mashup/moit/scheduler/StudyAdjustAbsenceScheduler.kt b/moit-api/src/main/kotlin/com/mashup/moit/scheduler/StudyAdjustAbsenceScheduler.kt index 46a3fac7..2dc80281 100644 --- a/moit-api/src/main/kotlin/com/mashup/moit/scheduler/StudyAdjustAbsenceScheduler.kt +++ b/moit-api/src/main/kotlin/com/mashup/moit/scheduler/StudyAdjustAbsenceScheduler.kt @@ -1,7 +1,6 @@ package com.mashup.moit.scheduler import com.mashup.moit.domain.attendance.AttendanceService -import com.mashup.moit.domain.fine.FineService import com.mashup.moit.domain.study.StudyService import com.mashup.moit.infra.event.EventProducer import com.mashup.moit.infra.event.StudyAttendanceEvent @@ -28,17 +27,15 @@ class StudyAdjustAbsenceScheduler( // 결석 확정을 지을 때 endAt을 현재 시간보다 15초 정도 유예기간을 줌. 5분마다 배치가 돌기 때문에 95% 시간 내에 끝난 스터디를 반환함 val scheduleContext = LocalDateTime.now() val undecided = studyService - .findUnfinalizedStudiesByEndAtBefore(LocalDateTime.now().minusSeconds(DECIDE_ABSENCE_RANGE_SECONDS)) - .map { it.id } + .findUnfinalizedStudiesByEndAtBefore(scheduleContext.minusSeconds(DECIDE_ABSENCE_RANGE_SECONDS)) logger.info("{} undecided studies start! Start adjusting absence status at {}.", undecided.size, scheduleContext) - studyService.findByStudyIds(undecided) - .forEach { study -> - attendanceService.adjustUndecidedAttendancesByStudyId(study.id) - .forEach { attendanceId -> - eventProducer.produce(StudyAttendanceEvent(attendanceId = attendanceId, moitId = study.moitId)) - } - } + undecided.forEach { study -> + attendanceService.adjustUndecidedAttendancesByStudyId(study.id) + .forEach { attendanceId -> + eventProducer.produce(StudyAttendanceEvent(attendanceId = attendanceId, moitId = study.moitId)) + } + } logger.info("Done adjusting absence status for {} studies, at {}", undecided.size, LocalDateTime.now()) } From 0c5bceb70d886f656feaad6fa433c6d5fec88935 Mon Sep 17 00:00:00 2001 From: "Jaemin.Park" Date: Sun, 30 Jul 2023 02:18:44 +0900 Subject: [PATCH 8/8] Fix creating fines logic for bulk --- .../com/mashup/moit/infra/event/MoitEvent.kt | 12 ++++++++ .../mashup/moit/infra/event/MoitEventTopic.kt | 4 +++ .../moit/infra/event/kafka/KafkaConsumer.kt | 28 ++++++++++++++++++- .../scheduler/StudyAdjustAbsenceScheduler.kt | 12 ++++---- 4 files changed, 50 insertions(+), 6 deletions(-) diff --git a/moit-api/src/main/kotlin/com/mashup/moit/infra/event/MoitEvent.kt b/moit-api/src/main/kotlin/com/mashup/moit/infra/event/MoitEvent.kt index fd1267a1..89af7022 100644 --- a/moit-api/src/main/kotlin/com/mashup/moit/infra/event/MoitEvent.kt +++ b/moit-api/src/main/kotlin/com/mashup/moit/infra/event/MoitEvent.kt @@ -16,6 +16,12 @@ data class StudyAttendanceEvent(val attendanceId: Long, val moitId: Long) : Moit } } +data class StudyAttendanceEventBulk(val attendanceIdWithMoitIds: List>) : MoitEvent { + override fun getTopic(): String { + return KafkaEventTopic.STUDY_ATTENDANCE_BULK + } +} + data class StudyInitializeEvent(val studyId: Long) : MoitEvent { override fun getTopic(): String { return KafkaEventTopic.STUDY_INITIALIZE @@ -28,6 +34,12 @@ data class FineCreateEvent(val fineId: Long) : MoitEvent { } } +data class FineCreateEventBulk(val fineIds: Set) : MoitEvent { + override fun getTopic(): String { + return KafkaEventTopic.FINE_CREATE_BULK + } +} + data class FineApproveEvent(val fineId: Long) : MoitEvent { override fun getTopic(): String { return KafkaEventTopic.FINE_APPROVE diff --git a/moit-api/src/main/kotlin/com/mashup/moit/infra/event/MoitEventTopic.kt b/moit-api/src/main/kotlin/com/mashup/moit/infra/event/MoitEventTopic.kt index f3ffa332..af989699 100644 --- a/moit-api/src/main/kotlin/com/mashup/moit/infra/event/MoitEventTopic.kt +++ b/moit-api/src/main/kotlin/com/mashup/moit/infra/event/MoitEventTopic.kt @@ -4,7 +4,9 @@ object KafkaEventTopic { const val MOIT_CREATE = "moit_create" const val STUDY_INITIALIZE = "study_initialize" const val STUDY_ATTENDANCE = "study_attendance" + const val STUDY_ATTENDANCE_BULK = "study_attendance_bulk" const val FINE_CREATE = "fine_create" + const val FINE_CREATE_BULK = "fine_create_bulk" const val FINE_APPROVE = "fine_approve" } @@ -12,6 +14,8 @@ object KafkaConsumerGroup { const val MOIT_CREATE_STUDY_CREATE = "moit_create_study_create" const val STUDY_INITIALIZE_BANNER_UPDATE = "study_initialize_banner_update" const val STUDY_ATTENDANCE_FINE_CREATE = "study_attendance_fine_create" + const val STUDY_ATTENDANCE_FINE_CREATE_BULK = "study_attendance_fine_create_bulk" const val FINE_CREATE_BANNER_UPDATE = "fine_create_banner_update" + const val FINE_CREATE_BANNER_UPDATE_BULK = "fine_create_banner_update_bulk" const val FINE_APPROVE_BANNER_UPDATE = "fine_approve_banner_update" } diff --git a/moit-api/src/main/kotlin/com/mashup/moit/infra/event/kafka/KafkaConsumer.kt b/moit-api/src/main/kotlin/com/mashup/moit/infra/event/kafka/KafkaConsumer.kt index 26092ad1..0f48afb8 100644 --- a/moit-api/src/main/kotlin/com/mashup/moit/infra/event/kafka/KafkaConsumer.kt +++ b/moit-api/src/main/kotlin/com/mashup/moit/infra/event/kafka/KafkaConsumer.kt @@ -8,10 +8,12 @@ import com.mashup.moit.domain.study.StudyService import com.mashup.moit.infra.event.EventProducer import com.mashup.moit.infra.event.FineApproveEvent import com.mashup.moit.infra.event.FineCreateEvent -import com.mashup.moit.infra.event.StudyAttendanceEvent +import com.mashup.moit.infra.event.FineCreateEventBulk import com.mashup.moit.infra.event.KafkaConsumerGroup import com.mashup.moit.infra.event.KafkaEventTopic import com.mashup.moit.infra.event.MoitCreateEvent +import com.mashup.moit.infra.event.StudyAttendanceEvent +import com.mashup.moit.infra.event.StudyAttendanceEventBulk import com.mashup.moit.infra.event.StudyInitializeEvent import org.slf4j.Logger import org.slf4j.LoggerFactory @@ -56,6 +58,19 @@ class KafkaConsumer( } } + @KafkaListener( + topics = [KafkaEventTopic.STUDY_ATTENDANCE_BULK], + groupId = KafkaConsumerGroup.STUDY_ATTENDANCE_FINE_CREATE_BULK, + ) + fun consumeStudyAttendancesEvent(event: StudyAttendanceEventBulk) { + log.debug("consumeStudyAttendancesEventBulk called: {}", event) + val fineIds = mutableSetOf() + event.attendanceIdWithMoitIds.forEach { (attendanceId, moitId) -> + fineService.create(attendanceId, moitId)?.let { fine -> fineIds.add(fine.id) } + } + eventProducer.produce(FineCreateEventBulk(fineIds)) + } + @KafkaListener( topics = [KafkaEventTopic.FINE_CREATE], groupId = KafkaConsumerGroup.FINE_CREATE_BANNER_UPDATE, @@ -65,6 +80,17 @@ class KafkaConsumer( bannerService.update(MoitUnapprovedFineExistBannerUpdateRequest(event.fineId)) } + @KafkaListener( + topics = [KafkaEventTopic.FINE_CREATE_BULK], + groupId = KafkaConsumerGroup.FINE_CREATE_BANNER_UPDATE_BULK, + ) + fun consumeFineCreateEventBulk(event: FineCreateEventBulk) { + log.debug("consumeFineCreateEventBulk called: {}", event) + event.fineIds.forEach { fineId -> + bannerService.update(MoitUnapprovedFineExistBannerUpdateRequest(fineId)) + } + } + @KafkaListener( topics = [KafkaEventTopic.FINE_APPROVE], groupId = KafkaConsumerGroup.FINE_APPROVE_BANNER_UPDATE, diff --git a/moit-api/src/main/kotlin/com/mashup/moit/scheduler/StudyAdjustAbsenceScheduler.kt b/moit-api/src/main/kotlin/com/mashup/moit/scheduler/StudyAdjustAbsenceScheduler.kt index 2dc80281..775caeae 100644 --- a/moit-api/src/main/kotlin/com/mashup/moit/scheduler/StudyAdjustAbsenceScheduler.kt +++ b/moit-api/src/main/kotlin/com/mashup/moit/scheduler/StudyAdjustAbsenceScheduler.kt @@ -3,7 +3,7 @@ package com.mashup.moit.scheduler import com.mashup.moit.domain.attendance.AttendanceService import com.mashup.moit.domain.study.StudyService import com.mashup.moit.infra.event.EventProducer -import com.mashup.moit.infra.event.StudyAttendanceEvent +import com.mashup.moit.infra.event.StudyAttendanceEventBulk import org.slf4j.Logger import org.slf4j.LoggerFactory import org.springframework.scheduling.annotation.Async @@ -30,12 +30,14 @@ class StudyAdjustAbsenceScheduler( .findUnfinalizedStudiesByEndAtBefore(scheduleContext.minusSeconds(DECIDE_ABSENCE_RANGE_SECONDS)) logger.info("{} undecided studies start! Start adjusting absence status at {}.", undecided.size, scheduleContext) + val attendanceIdWithMoitIds = mutableListOf>() undecided.forEach { study -> - attendanceService.adjustUndecidedAttendancesByStudyId(study.id) - .forEach { attendanceId -> - eventProducer.produce(StudyAttendanceEvent(attendanceId = attendanceId, moitId = study.moitId)) - } + attendanceIdWithMoitIds.addAll( + attendanceService.adjustUndecidedAttendancesByStudyId(study.id) + .map { attendanceId -> attendanceId to study.moitId } + ) } + eventProducer.produce(StudyAttendanceEventBulk(attendanceIdWithMoitIds)) logger.info("Done adjusting absence status for {} studies, at {}", undecided.size, LocalDateTime.now()) }