diff --git a/src/main/kotlin/com/photi/server/config/batch/job/ChallengeStatusEndJobConfig.kt b/src/main/kotlin/com/photi/server/config/batch/job/ChallengeStatusEndJobConfig.kt index 4e95bc90..0b33a6fe 100644 --- a/src/main/kotlin/com/photi/server/config/batch/job/ChallengeStatusEndJobConfig.kt +++ b/src/main/kotlin/com/photi/server/config/batch/job/ChallengeStatusEndJobConfig.kt @@ -29,9 +29,9 @@ class ChallengeStatusEndJobConfig( private val jobRepository: JobRepository, ) { - @Bean(JOB_NAME) + @Bean(CHALLENGE_END_JOB_NAME) fun job(): Job { - return JobBuilder(JOB_NAME, jobRepository) + return JobBuilder(CHALLENGE_END_JOB_NAME, jobRepository) .start(step()) .build() } @@ -82,7 +82,7 @@ class ChallengeStatusEndJobConfig( } companion object { - const val JOB_NAME = "챌린지종료상태" - const val BEAN_PREFIX = JOB_NAME + "_" + const val CHALLENGE_END_JOB_NAME = "챌린지종료상태" + const val BEAN_PREFIX = CHALLENGE_END_JOB_NAME + "_" } } diff --git a/src/main/kotlin/com/photi/server/config/batch/job/ContactReRegisterJobConfig.kt b/src/main/kotlin/com/photi/server/config/batch/job/ContactReRegisterJobConfig.kt new file mode 100644 index 00000000..de9659c6 --- /dev/null +++ b/src/main/kotlin/com/photi/server/config/batch/job/ContactReRegisterJobConfig.kt @@ -0,0 +1,90 @@ +package com.photi.server.config.batch.job + +import com.photi.server.domain.user.Contact +import jakarta.persistence.EntityManagerFactory +import org.springframework.batch.core.Job +import org.springframework.batch.core.Step +import org.springframework.batch.core.configuration.annotation.JobScope +import org.springframework.batch.core.configuration.annotation.StepScope +import org.springframework.batch.core.job.builder.JobBuilder +import org.springframework.batch.core.repository.JobRepository +import org.springframework.batch.core.step.builder.StepBuilder +import org.springframework.batch.item.ItemProcessor +import org.springframework.batch.item.database.JpaItemWriter +import org.springframework.batch.item.database.JpaPagingItemReader +import org.springframework.batch.item.database.builder.JpaPagingItemReaderBuilder +import org.springframework.beans.factory.annotation.Value +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import org.springframework.transaction.PlatformTransactionManager +import java.time.LocalDate + +@Configuration +class ContactReRegisterJobConfig( + + @Value("\${spring.batch.chunk-size}") + private val chunkSize: Int, + private val entityManagerFactory: EntityManagerFactory, + private val transactionManager: PlatformTransactionManager, + private val jobRepository: JobRepository, +) { + + @Bean(CONTACT_RE_REGISTER_JOB_NAME) + fun job(): Job { + return JobBuilder(CONTACT_RE_REGISTER_JOB_NAME, jobRepository) + .start(step()) + .build() + } + + @Bean(BEAN_PREFIX + "step") + @JobScope + fun step(): Step { + return StepBuilder(BEAN_PREFIX + "step", jobRepository) + .chunk(chunkSize, transactionManager) + .reader(itemReader(null)) + .processor(itemProcessor()) + .writer(itemWriter()) + .build() + } + + @Bean(BEAN_PREFIX + "itemReader") + @StepScope + fun itemReader(@Value("#{jobParameters[date]}") date: LocalDate?): JpaPagingItemReader { + val minusMonthDateTime = date?.minusMonths(MONTH_TO_SUBTRACT)?.atStartOfDay() + return JpaPagingItemReaderBuilder() + .name(BEAN_PREFIX + "itemReader") + .entityManagerFactory(entityManagerFactory) + .pageSize(chunkSize) + .queryString( + """ + SELECT c FROM Contact c + WHERE c.isDeleted = true + AND c.deletedDate <= :date + ORDER BY c.id ASC + """.trimIndent() + ) + .parameterValues(mapOf("date" to minusMonthDateTime)) + .build() + } + + @Bean(BEAN_PREFIX + "itemProcessor") + fun itemProcessor(): ItemProcessor { + return ItemProcessor { + it.updateReRegisterStatus() + it + } + } + + @Bean(BEAN_PREFIX + "itemWriter") + fun itemWriter(): JpaItemWriter { + return JpaItemWriter().apply { + setEntityManagerFactory(entityManagerFactory) + } + } + + companion object { + const val CONTACT_RE_REGISTER_JOB_NAME = "회원재가입가능상태" + const val BEAN_PREFIX = CONTACT_RE_REGISTER_JOB_NAME + "_" + const val MONTH_TO_SUBTRACT = 1L + } +} diff --git a/src/main/kotlin/com/photi/server/config/batch/scheduler/JobScheduler.kt b/src/main/kotlin/com/photi/server/config/batch/scheduler/JobScheduler.kt index 2c541231..31a5dded 100644 --- a/src/main/kotlin/com/photi/server/config/batch/scheduler/JobScheduler.kt +++ b/src/main/kotlin/com/photi/server/config/batch/scheduler/JobScheduler.kt @@ -1,5 +1,7 @@ package com.photi.server.config.batch.scheduler +import com.photi.server.config.batch.job.ChallengeStatusEndJobConfig.Companion.CHALLENGE_END_JOB_NAME +import com.photi.server.config.batch.job.ContactReRegisterJobConfig.Companion.CONTACT_RE_REGISTER_JOB_NAME import org.springframework.batch.core.JobParametersBuilder import org.springframework.batch.core.JobParametersInvalidException import org.springframework.batch.core.configuration.JobRegistry @@ -18,11 +20,20 @@ class JobScheduler( private val jobRegistry: JobRegistry, ) { - @Scheduled(cron = "0 * 3 * * *") - fun runJob() { + @Scheduled(cron = "0 0 3 * * *") + fun runChallengeEndJob() { + runJob(CHALLENGE_END_JOB_NAME) + } + + @Scheduled(cron = "0 0 4 * * *") + fun runContactReRegisterJob() { + runJob(CONTACT_RE_REGISTER_JOB_NAME) + } + + fun runJob(jobName: String) { val date = LocalDate.now().toString() try { - val job = jobRegistry.getJob(JOB_NAME) + val job = jobRegistry.getJob(jobName) val jobParameters = JobParametersBuilder() .addString(JOB_PARAMETER, date) .toJobParameters() @@ -41,7 +52,6 @@ class JobScheduler( } companion object { - const val JOB_NAME = "챌린지종료상태" const val JOB_PARAMETER = "date" } } diff --git a/src/main/kotlin/com/photi/server/domain/user/Contact.kt b/src/main/kotlin/com/photi/server/domain/user/Contact.kt index f8678a63..f23c93f7 100644 --- a/src/main/kotlin/com/photi/server/domain/user/Contact.kt +++ b/src/main/kotlin/com/photi/server/domain/user/Contact.kt @@ -54,4 +54,9 @@ class Contact( isDeleted = true deletedDate = LocalDateTime.now() } + + fun updateReRegisterStatus() { + isDeleted = false + deletedDate = null + } } \ No newline at end of file