From f2b6438341a7d5ecfd7334f6ee4b731e84258373 Mon Sep 17 00:00:00 2001 From: hyeonjeongs Date: Mon, 26 Feb 2024 17:25:43 +0900 Subject: [PATCH] =?UTF-8?q?YEL-214=20[feat]=20lunch=20event=20spring=20bat?= =?UTF-8?q?ch,=20scheduler=20=EC=97=B0=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../user/repository/UserJpaRepository.java | 1 - .../user/repository/UserRepository.java | 1 - .../infrastructure/batch/ChunkProcessor.java | 4 -- .../infrastructure/batch/ChunkReader.java | 58 ++++++++++++++++++- .../batch/JobConfiguration.java | 4 +- .../batch/StepConfiguration.java | 5 +- .../scheduler/EventScheduler.java | 49 ++++++++++++++++ .../domain/user/FakeUserRepository.java | 9 --- 8 files changed, 110 insertions(+), 21 deletions(-) create mode 100644 src/main/java/com/yello/server/infrastructure/scheduler/EventScheduler.java diff --git a/src/main/java/com/yello/server/domain/user/repository/UserJpaRepository.java b/src/main/java/com/yello/server/domain/user/repository/UserJpaRepository.java index 297f7cb4..35fc50e2 100644 --- a/src/main/java/com/yello/server/domain/user/repository/UserJpaRepository.java +++ b/src/main/java/com/yello/server/domain/user/repository/UserJpaRepository.java @@ -134,6 +134,5 @@ List findAllByOtherGroupContainingYelloId(@Param("groupName") String group + "where LOWER(u.name) like LOWER(CONCAT('%', :name, '%'))") Page findAllByNameContaining(Pageable pageable, @Param("name") String name); - Page findAllByPageable(Pageable pageable); } diff --git a/src/main/java/com/yello/server/domain/user/repository/UserRepository.java b/src/main/java/com/yello/server/domain/user/repository/UserRepository.java index c3f7eff2..0c9d9256 100644 --- a/src/main/java/com/yello/server/domain/user/repository/UserRepository.java +++ b/src/main/java/com/yello/server/domain/user/repository/UserRepository.java @@ -76,5 +76,4 @@ List findAllByOtherGroupContainingYelloId(String groupName, String keyword void delete(User user); - Page findAllByPageable(Pageable pageable); } diff --git a/src/main/java/com/yello/server/infrastructure/batch/ChunkProcessor.java b/src/main/java/com/yello/server/infrastructure/batch/ChunkProcessor.java index d2132e51..4fc93ecd 100644 --- a/src/main/java/com/yello/server/infrastructure/batch/ChunkProcessor.java +++ b/src/main/java/com/yello/server/infrastructure/batch/ChunkProcessor.java @@ -1,11 +1,7 @@ package com.yello.server.infrastructure.batch; -import com.yello.server.domain.user.entity.User; import lombok.RequiredArgsConstructor; -import org.springframework.batch.core.configuration.annotation.StepScope; -import org.springframework.batch.item.ItemProcessor; -import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @RequiredArgsConstructor diff --git a/src/main/java/com/yello/server/infrastructure/batch/ChunkReader.java b/src/main/java/com/yello/server/infrastructure/batch/ChunkReader.java index 9665eba9..3a777cd2 100644 --- a/src/main/java/com/yello/server/infrastructure/batch/ChunkReader.java +++ b/src/main/java/com/yello/server/infrastructure/batch/ChunkReader.java @@ -2,25 +2,38 @@ import com.yello.server.domain.user.entity.User; import com.yello.server.domain.user.repository.UserJpaRepository; -import com.yello.server.domain.user.repository.UserRepository; +import jakarta.persistence.EntityManagerFactory; import lombok.RequiredArgsConstructor; import org.springframework.batch.core.configuration.annotation.StepScope; import org.springframework.batch.item.data.RepositoryItemReader; import org.springframework.batch.item.data.builder.RepositoryItemReaderBuilder; +import org.springframework.batch.item.database.JdbcPagingItemReader; +import org.springframework.batch.item.database.JpaPagingItemReader; +import org.springframework.batch.item.database.Order; +import org.springframework.batch.item.database.PagingQueryProvider; +import org.springframework.batch.item.database.builder.JdbcPagingItemReaderBuilder; +import org.springframework.batch.item.database.builder.JpaPagingItemReaderBuilder; +import org.springframework.batch.item.database.support.SqlPagingQueryProviderFactoryBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.domain.Sort; +import org.springframework.jdbc.core.BeanPropertyRowMapper; +import javax.sql.DataSource; import java.util.Collections; +import java.util.HashMap; +import java.util.Map; @RequiredArgsConstructor @Configuration public class ChunkReader { private final UserJpaRepository userRepository; + private final EntityManagerFactory entityManagerFactory; + private final DataSource dataSource; @Bean @StepScope - public RepositoryItemReader userDataReader() { + public RepositoryItemReader usersDataRepositoryItemReader() { return new RepositoryItemReaderBuilder() .name("userDataReader") @@ -30,4 +43,45 @@ public RepositoryItemReader userDataReader() { .sorts(Collections.singletonMap("id", Sort.Direction.ASC)) .build(); } + + @Bean + @StepScope + public JpaPagingItemReader userDataJpaPagingItemReader() { + + return new JpaPagingItemReaderBuilder() + .name("userDataReader") + .pageSize(100) + .queryString("SELECT u FROM USER u ORDER BY id") + .entityManagerFactory(entityManagerFactory) + .build(); + } + + @Bean + @StepScope + public JdbcPagingItemReader userDataJdbcPagingItemReader() throws Exception { + + return new JdbcPagingItemReaderBuilder() + .pageSize(100) + .fetchSize(100) + .dataSource(dataSource) + .rowMapper(new BeanPropertyRowMapper<>(User.class)) + .queryProvider(createUserDataQueryProvider()) + .name("jdbcPagingItemReader") + .build(); + } + + @Bean + public PagingQueryProvider createUserDataQueryProvider() throws Exception { + SqlPagingQueryProviderFactoryBean queryProvider = new SqlPagingQueryProviderFactoryBean(); + queryProvider.setDataSource(dataSource); + queryProvider.setSelectClause("id"); + queryProvider.setFromClause("from user"); + + Map sortKeys = new HashMap<>(); + sortKeys.put("id", Order.ASCENDING); + queryProvider.setSortKeys(sortKeys); + + return queryProvider.getObject(); + + } } diff --git a/src/main/java/com/yello/server/infrastructure/batch/JobConfiguration.java b/src/main/java/com/yello/server/infrastructure/batch/JobConfiguration.java index 41084f11..8bfe424d 100644 --- a/src/main/java/com/yello/server/infrastructure/batch/JobConfiguration.java +++ b/src/main/java/com/yello/server/infrastructure/batch/JobConfiguration.java @@ -16,8 +16,8 @@ public class JobConfiguration { private final StepConfiguration stepConfiguration; @Bean - public Job myJob(JobRepository jobRepository, PlatformTransactionManager transactionManager) { - return new JobBuilder("myJob", jobRepository) + public Job lunchEventJob(JobRepository jobRepository, PlatformTransactionManager transactionManager) throws Exception { + return new JobBuilder("lunchEventJob", jobRepository) .start(stepConfiguration.lunchEventAlarmStep(jobRepository, transactionManager)) .build(); } diff --git a/src/main/java/com/yello/server/infrastructure/batch/StepConfiguration.java b/src/main/java/com/yello/server/infrastructure/batch/StepConfiguration.java index affd9d0c..a5746343 100644 --- a/src/main/java/com/yello/server/infrastructure/batch/StepConfiguration.java +++ b/src/main/java/com/yello/server/infrastructure/batch/StepConfiguration.java @@ -12,6 +12,7 @@ import org.springframework.batch.repeat.RepeatStatus; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.Scheduled; import org.springframework.transaction.PlatformTransactionManager; @Slf4j @@ -23,10 +24,10 @@ public class StepConfiguration { private final ChunkWriter chunkWriter; @Bean - public Step lunchEventAlarmStep(JobRepository jobRepository, PlatformTransactionManager transactionManager) { + public Step lunchEventAlarmStep(JobRepository jobRepository, PlatformTransactionManager transactionManager) throws Exception { return new StepBuilder("lunchEventStep", jobRepository) .chunk(100, transactionManager) - .reader(chunkReader.userDataReader()) + .reader(chunkReader.userDataJdbcPagingItemReader()) .writer(chunkWriter.lunchEventWriter()) .build(); } diff --git a/src/main/java/com/yello/server/infrastructure/scheduler/EventScheduler.java b/src/main/java/com/yello/server/infrastructure/scheduler/EventScheduler.java new file mode 100644 index 00000000..641a4525 --- /dev/null +++ b/src/main/java/com/yello/server/infrastructure/scheduler/EventScheduler.java @@ -0,0 +1,49 @@ +package com.yello.server.infrastructure.scheduler; + + +import com.yello.server.infrastructure.batch.JobConfiguration; +import lombok.RequiredArgsConstructor; +import org.springframework.batch.core.JobParameter; +import org.springframework.batch.core.JobParameters; +import org.springframework.batch.core.JobParametersBuilder; +import org.springframework.batch.core.JobParametersInvalidException; +import org.springframework.batch.core.launch.JobLauncher; +import org.springframework.batch.core.repository.JobExecutionAlreadyRunningException; +import org.springframework.batch.core.repository.JobInstanceAlreadyCompleteException; +import org.springframework.batch.core.repository.JobRepository; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; +import org.springframework.transaction.PlatformTransactionManager; + +import java.util.Date; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +@Component +@RequiredArgsConstructor +public class EventScheduler { + + private final JobLauncher jobLauncher; + private final JobConfiguration jobConfiguration; + private final JobRepository jobRepository; + private final PlatformTransactionManager transactionManager; + + @Scheduled(cron="0 0 12 * * ?") + public void lunchEventRunJob() { + + //JobParamter의 역할은 반복해서 실행되는 Job의 유일한 ID임, 동일한 값이 세팅되면 두번째부터 실행안됨) + JobParameters jobParameters = new JobParametersBuilder() + .addString("uuid", UUID.randomUUID().toString()) + .toJobParameters(); + + try { + jobLauncher.run(jobConfiguration.lunchEventJob(jobRepository, transactionManager), jobParameters); + } catch (JobExecutionAlreadyRunningException | JobInstanceAlreadyCompleteException + | JobParametersInvalidException | org.springframework.batch.core.repository.JobRestartException e) { + System.out.println(e.getMessage()); + } catch (Exception e) { + throw new RuntimeException(e); + } + } +} diff --git a/src/test/java/com/yello/server/domain/user/FakeUserRepository.java b/src/test/java/com/yello/server/domain/user/FakeUserRepository.java index 11e9ed20..569a3e48 100644 --- a/src/test/java/com/yello/server/domain/user/FakeUserRepository.java +++ b/src/test/java/com/yello/server/domain/user/FakeUserRepository.java @@ -321,13 +321,4 @@ public Page findAllByNameContaining(Pageable pageable, String name) { public void delete(User user) { data.remove(user); } - - @Override - public Page findAllByPageable(Pageable pageable) { - final List userList = data.stream() - .skip(pageable.getOffset()) - .limit(pageable.getPageSize()) - .toList(); - return new PageImpl<>(userList); - } }