From 444716885dfdeee172f06b3100eb8616620ee9bb Mon Sep 17 00:00:00 2001 From: hyeonjeongs Date: Mon, 26 Feb 2024 12:17:16 +0900 Subject: [PATCH 01/16] YEL-214 [setting] spring batch setting --- build.gradle | 5 +++++ src/main/java/com/yello/server/ServerApplication.java | 4 ++++ .../server/domain/user/repository/UserJpaRepository.java | 3 +++ .../server/domain/user/repository/UserRepository.java | 2 ++ .../domain/user/repository/UserRepositoryImpl.java | 5 +++++ .../com/yello/server/domain/user/FakeUserRepository.java | 9 +++++++++ 6 files changed, 28 insertions(+) diff --git a/build.gradle b/build.gradle index c9a03190..6a48428a 100644 --- a/build.gradle +++ b/build.gradle @@ -88,6 +88,7 @@ dependencies { testImplementation 'org.springframework.restdocs:spring-restdocs-mockmvc' testImplementation 'org.springframework.security:spring-security-test' testImplementation 'org.mockito:mockito-inline:5.2.0' + testImplementation 'org.springframework.batch:spring-batch-test' // jwt decode implementation 'org.bouncycastle:bcprov-jdk15on:1.69' @@ -109,6 +110,10 @@ dependencies { // tink implementation 'com.google.crypto.tink:tink-android:1.4.0-rc1' implementation 'com.google.crypto.tink:apps-rewardedads:1.10.0' + + // spring batch + implementation 'org.springframework.boot:spring-boot-starter-batch' + } asciidoctor { diff --git a/src/main/java/com/yello/server/ServerApplication.java b/src/main/java/com/yello/server/ServerApplication.java index 91b6def6..59d267b5 100644 --- a/src/main/java/com/yello/server/ServerApplication.java +++ b/src/main/java/com/yello/server/ServerApplication.java @@ -1,10 +1,14 @@ package com.yello.server; +import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing; +import org.springframework.batch.core.configuration.support.DefaultBatchConfiguration; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; @SpringBootApplication +@ConditionalOnMissingBean(value = DefaultBatchConfiguration.class, annotation = EnableBatchProcessing.class) public class ServerApplication { public static void main(String[] args) { 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 01d64b09..297f7cb4 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 @@ -133,4 +133,7 @@ List findAllByOtherGroupContainingYelloId(@Param("groupName") String group @Query("select u from User u " + "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 2ef67768..c3f7eff2 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 @@ -75,4 +75,6 @@ List findAllByOtherGroupContainingYelloId(String groupName, String keyword Page findAllByNameContaining(Pageable pageable, String name); void delete(User user); + + Page findAllByPageable(Pageable pageable); } diff --git a/src/main/java/com/yello/server/domain/user/repository/UserRepositoryImpl.java b/src/main/java/com/yello/server/domain/user/repository/UserRepositoryImpl.java index aa1e8df4..d7acebae 100644 --- a/src/main/java/com/yello/server/domain/user/repository/UserRepositoryImpl.java +++ b/src/main/java/com/yello/server/domain/user/repository/UserRepositoryImpl.java @@ -192,4 +192,9 @@ public Page findAllByNameContaining(Pageable pageable, String name) { public void delete(User user) { userJpaRepository.delete(user); } + + @Override + public Page findAllByPageable(Pageable pageable) { + return userJpaRepository.findAllByPageable(pageable); + } } 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 569a3e48..11e9ed20 100644 --- a/src/test/java/com/yello/server/domain/user/FakeUserRepository.java +++ b/src/test/java/com/yello/server/domain/user/FakeUserRepository.java @@ -321,4 +321,13 @@ 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); + } } From b025439a347f5b2c028803bd11021dff9283a1a1 Mon Sep 17 00:00:00 2001 From: hyeonjeongs Date: Mon, 26 Feb 2024 12:17:25 +0900 Subject: [PATCH 02/16] YEL-214 [setting] spring batch setting --- .../infrastructure/batch/ChunkProcessor.java | 20 ++++++++++ .../infrastructure/batch/ChunkReader.java | 33 +++++++++++++++ .../infrastructure/batch/ChunkWriter.java | 22 ++++++++++ .../batch/JobConfiguration.java | 26 ++++++++++++ .../batch/StepConfiguration.java | 40 +++++++++++++++++++ 5 files changed, 141 insertions(+) create mode 100644 src/main/java/com/yello/server/infrastructure/batch/ChunkProcessor.java create mode 100644 src/main/java/com/yello/server/infrastructure/batch/ChunkReader.java create mode 100644 src/main/java/com/yello/server/infrastructure/batch/ChunkWriter.java create mode 100644 src/main/java/com/yello/server/infrastructure/batch/JobConfiguration.java create mode 100644 src/main/java/com/yello/server/infrastructure/batch/StepConfiguration.java diff --git a/src/main/java/com/yello/server/infrastructure/batch/ChunkProcessor.java b/src/main/java/com/yello/server/infrastructure/batch/ChunkProcessor.java new file mode 100644 index 00000000..b9be89f7 --- /dev/null +++ b/src/main/java/com/yello/server/infrastructure/batch/ChunkProcessor.java @@ -0,0 +1,20 @@ +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 +@Configuration +public class ChunkProcessor { + + @Bean + @StepScope + public ItemProcessor lunchEventProcessor() { + return user -> new User); + } +} diff --git a/src/main/java/com/yello/server/infrastructure/batch/ChunkReader.java b/src/main/java/com/yello/server/infrastructure/batch/ChunkReader.java new file mode 100644 index 00000000..9665eba9 --- /dev/null +++ b/src/main/java/com/yello/server/infrastructure/batch/ChunkReader.java @@ -0,0 +1,33 @@ +package com.yello.server.infrastructure.batch; + +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 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.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.domain.Sort; + +import java.util.Collections; + +@RequiredArgsConstructor +@Configuration +public class ChunkReader { + private final UserJpaRepository userRepository; + + @Bean + @StepScope + public RepositoryItemReader userDataReader() { + + return new RepositoryItemReaderBuilder() + .name("userDataReader") + .repository(userRepository) + .methodName("findAllByPageable") + .pageSize(100) + .sorts(Collections.singletonMap("id", Sort.Direction.ASC)) + .build(); + } +} diff --git a/src/main/java/com/yello/server/infrastructure/batch/ChunkWriter.java b/src/main/java/com/yello/server/infrastructure/batch/ChunkWriter.java new file mode 100644 index 00000000..ae2d0b18 --- /dev/null +++ b/src/main/java/com/yello/server/infrastructure/batch/ChunkWriter.java @@ -0,0 +1,22 @@ +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.ItemWriter; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + + +@RequiredArgsConstructor +@Configuration +public class ChunkWriter { + + @Bean + @StepScope + public ItemWriter lunchEventWriter() { + return items -> items.forEach(item -> { + + }); + } +} diff --git a/src/main/java/com/yello/server/infrastructure/batch/JobConfiguration.java b/src/main/java/com/yello/server/infrastructure/batch/JobConfiguration.java new file mode 100644 index 00000000..41084f11 --- /dev/null +++ b/src/main/java/com/yello/server/infrastructure/batch/JobConfiguration.java @@ -0,0 +1,26 @@ +package com.yello.server.infrastructure.batch; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.batch.core.Job; +import org.springframework.batch.core.job.builder.JobBuilder; +import org.springframework.batch.core.repository.JobRepository; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.transaction.PlatformTransactionManager; + +@Slf4j +@RequiredArgsConstructor +@Configuration +public class JobConfiguration { + private final StepConfiguration stepConfiguration; + + @Bean + public Job myJob(JobRepository jobRepository, PlatformTransactionManager transactionManager) { + return new JobBuilder("myJob", 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 new file mode 100644 index 00000000..9b2a3708 --- /dev/null +++ b/src/main/java/com/yello/server/infrastructure/batch/StepConfiguration.java @@ -0,0 +1,40 @@ +package com.yello.server.infrastructure.batch; + +import com.yello.server.domain.user.entity.User; +import com.yello.server.domain.user.entity.UserData; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.batch.core.Job; +import org.springframework.batch.core.Step; +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.repeat.RepeatStatus; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.transaction.PlatformTransactionManager; + +@Slf4j +@RequiredArgsConstructor +@Configuration +public class StepConfiguration { + private final ChunkReader chunkReader; + private final ChunkProcessor chunkProcessor; + private final ChunkWriter chunkWriter; + + @Bean + public Step myStep(JobRepository jobRepository, PlatformTransactionManager transactionManager) { + return new StepBuilder("myStep", jobRepository) + .tasklet(((contribution, chunkContext) -> RepeatStatus.FINISHED), transactionManager) // or .chunk(chunkSize, transactionManager) + .build(); + } + + @Bean + public Step lunchEventAlarmStep(JobRepository jobRepository, PlatformTransactionManager transactionManager) { + return new StepBuilder("lunchEventStep", jobRepository) + .chunk(100, transactionManager) + .reader(chunkReader.userDataReader()) + .writer(chunkWriter.lunchEventWriter()) + .build(); + } +} From 926afde743949fa93fd58c96710cbfef0d64cbe2 Mon Sep 17 00:00:00 2001 From: hyeonjeongs Date: Mon, 26 Feb 2024 12:36:28 +0900 Subject: [PATCH 03/16] YEL-214 [feat] lunch event push alarm --- .../infrastructure/batch/ChunkProcessor.java | 5 -- .../infrastructure/batch/ChunkWriter.java | 5 +- .../batch/StepConfiguration.java | 7 --- .../firebase/dto/NotificationType.java | 3 +- .../dto/request/NotificationMessage.java | 8 +++ .../service/NotificationFcmService.java | 59 ++++++++++++------- .../firebase/service/NotificationService.java | 3 + 7 files changed, 54 insertions(+), 36 deletions(-) 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 b9be89f7..d2132e51 100644 --- a/src/main/java/com/yello/server/infrastructure/batch/ChunkProcessor.java +++ b/src/main/java/com/yello/server/infrastructure/batch/ChunkProcessor.java @@ -12,9 +12,4 @@ @Configuration public class ChunkProcessor { - @Bean - @StepScope - public ItemProcessor lunchEventProcessor() { - return user -> new User); - } } diff --git a/src/main/java/com/yello/server/infrastructure/batch/ChunkWriter.java b/src/main/java/com/yello/server/infrastructure/batch/ChunkWriter.java index ae2d0b18..8b3f8ed7 100644 --- a/src/main/java/com/yello/server/infrastructure/batch/ChunkWriter.java +++ b/src/main/java/com/yello/server/infrastructure/batch/ChunkWriter.java @@ -1,6 +1,7 @@ package com.yello.server.infrastructure.batch; import com.yello.server.domain.user.entity.User; +import com.yello.server.infrastructure.firebase.service.NotificationService; import lombok.RequiredArgsConstructor; import org.springframework.batch.core.configuration.annotation.StepScope; import org.springframework.batch.item.ItemWriter; @@ -11,12 +12,12 @@ @RequiredArgsConstructor @Configuration public class ChunkWriter { + private final NotificationService notificationService; @Bean @StepScope public ItemWriter lunchEventWriter() { - return items -> items.forEach(item -> { - }); + return items -> items.forEach(notificationService::sendLunchEventNotification); } } 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 9b2a3708..affd9d0c 100644 --- a/src/main/java/com/yello/server/infrastructure/batch/StepConfiguration.java +++ b/src/main/java/com/yello/server/infrastructure/batch/StepConfiguration.java @@ -22,13 +22,6 @@ public class StepConfiguration { private final ChunkProcessor chunkProcessor; private final ChunkWriter chunkWriter; - @Bean - public Step myStep(JobRepository jobRepository, PlatformTransactionManager transactionManager) { - return new StepBuilder("myStep", jobRepository) - .tasklet(((contribution, chunkContext) -> RepeatStatus.FINISHED), transactionManager) // or .chunk(chunkSize, transactionManager) - .build(); - } - @Bean public Step lunchEventAlarmStep(JobRepository jobRepository, PlatformTransactionManager transactionManager) { return new StepBuilder("lunchEventStep", jobRepository) diff --git a/src/main/java/com/yello/server/infrastructure/firebase/dto/NotificationType.java b/src/main/java/com/yello/server/infrastructure/firebase/dto/NotificationType.java index 27e7b989..f940b3bd 100644 --- a/src/main/java/com/yello/server/infrastructure/firebase/dto/NotificationType.java +++ b/src/main/java/com/yello/server/infrastructure/firebase/dto/NotificationType.java @@ -4,5 +4,6 @@ public enum NotificationType { NEW_VOTE, VOTE_AVAILABLE, NEW_FRIEND, - RECOMMEND + RECOMMEND, + LUNCH_EVENT } diff --git a/src/main/java/com/yello/server/infrastructure/firebase/dto/request/NotificationMessage.java b/src/main/java/com/yello/server/infrastructure/firebase/dto/request/NotificationMessage.java index f452069b..430e60a0 100644 --- a/src/main/java/com/yello/server/infrastructure/firebase/dto/request/NotificationMessage.java +++ b/src/main/java/com/yello/server/infrastructure/firebase/dto/request/NotificationMessage.java @@ -52,6 +52,14 @@ public static NotificationMessage toYelloNotificationContent(Vote vote) { .build(); } + public static NotificationMessage toAllUserLunchEventNotificationContent() { + return NotificationMessage.builder() + .title("우리 학교 선착순 30명 열람권 뿌린다!") + .message("지금부터 14시까지\uD83D\uDD25 사라지기 전에 바로 확인해보세요!") + .type(NotificationType.LUNCH_EVENT) + .build(); + } + public static NotificationMessage toYelloNotificationCustomContent( NotificationCustomMessage message) { diff --git a/src/main/java/com/yello/server/infrastructure/firebase/service/NotificationFcmService.java b/src/main/java/com/yello/server/infrastructure/firebase/service/NotificationFcmService.java index b110e0c3..c4d1a6cc 100644 --- a/src/main/java/com/yello/server/infrastructure/firebase/service/NotificationFcmService.java +++ b/src/main/java/com/yello/server/infrastructure/firebase/service/NotificationFcmService.java @@ -10,12 +10,13 @@ import com.yello.server.infrastructure.firebase.dto.request.NotificationCustomMessage; import com.yello.server.infrastructure.firebase.dto.request.NotificationMessage; import com.yello.server.infrastructure.firebase.manager.FCMManager; -import java.util.Objects; import lombok.Builder; import lombok.RequiredArgsConstructor; import lombok.extern.log4j.Log4j2; import org.springframework.stereotype.Service; +import java.util.Objects; + @Log4j2 @Builder @Service @@ -29,11 +30,11 @@ public class NotificationFcmService implements NotificationService { @Override public void sendRecommendNotification(User user, User target) { NotificationMessage notificationMessage = - NotificationMessage.toRecommendNotificationContent(user); + NotificationMessage.toRecommendNotificationContent(user); if (target.getDeviceToken() != null && !Objects.equals(target.getDeviceToken(), "")) { final Message message = - fcmManager.createMessage(target.getDeviceToken(), notificationMessage); + fcmManager.createMessage(target.getDeviceToken(), notificationMessage); fcmManager.send(message); } } @@ -43,13 +44,13 @@ public void sendYelloNotification(Vote vote) { final User receiver = vote.getReceiver(); NotificationMessage notificationMessage = - NotificationMessage.toYelloNotificationContent(vote); + NotificationMessage.toYelloNotificationContent(vote); final String path = "/api/v1/vote/" + vote.getId().toString(); if (receiver.getDeviceToken() != null && !Objects.equals(receiver.getDeviceToken(), "")) { final Message message = - fcmManager.createMessage(receiver.getDeviceToken(), notificationMessage, path); + fcmManager.createMessage(receiver.getDeviceToken(), notificationMessage, path); fcmManager.send(message); } } @@ -60,11 +61,11 @@ public void sendFriendNotification(Friend friend) { final User sender = friend.getUser(); NotificationMessage notificationMessage = - NotificationMessage.toFriendNotificationContent(sender); + NotificationMessage.toFriendNotificationContent(sender); if (receiver.getDeviceToken() != null && !Objects.equals(receiver.getDeviceToken(), "")) { final Message message = - fcmManager.createMessage(receiver.getDeviceToken(), notificationMessage); + fcmManager.createMessage(receiver.getDeviceToken(), notificationMessage); fcmManager.send(message); } } @@ -74,12 +75,12 @@ public void sendVoteAvailableNotification(Long receiverId) { final User receiveUser = userRepository.getById(receiverId); NotificationMessage notificationMessage = - NotificationMessage.toVoteAvailableNotificationContent(); + NotificationMessage.toVoteAvailableNotificationContent(); if (receiveUser.getDeviceToken() != null && !Objects.equals(receiveUser.getDeviceToken(), - "")) { + "")) { final Message message = - fcmManager.createMessage(receiveUser.getDeviceToken(), notificationMessage); + fcmManager.createMessage(receiveUser.getDeviceToken(), notificationMessage); fcmManager.send(message); log.info("[rabbitmq] successfully send notification!"); } @@ -89,19 +90,19 @@ public void sendVoteAvailableNotification(Long receiverId) { public void sendCustomNotification(NotificationCustomMessage request) { request.userIdList().stream() - .forEach(userId -> { - final User receiver = userRepository.getById(userId); + .forEach(userId -> { + final User receiver = userRepository.getById(userId); - NotificationMessage notificationMessage = - NotificationMessage.toYelloNotificationCustomContent(request); + NotificationMessage notificationMessage = + NotificationMessage.toYelloNotificationCustomContent(request); - if (receiver.getDeviceToken() != null && !Objects.equals(receiver.getDeviceToken(), - "")) { - final Message message = - fcmManager.createMessage(receiver.getDeviceToken(), notificationMessage); - fcmManager.send(message); - } - }); + if (receiver.getDeviceToken() != null && !Objects.equals(receiver.getDeviceToken(), + "")) { + final Message message = + fcmManager.createMessage(receiver.getDeviceToken(), notificationMessage); + fcmManager.send(message); + } + }); } @@ -116,4 +117,20 @@ public EmptyObject adminSendCustomNotification(Long adminId, NotificationCustomM return EmptyObject.builder().build(); } + + @Override + public void sendLunchEventNotification(User user) { + final User receiver = userRepository.getById(user.getId()); + + NotificationMessage notificationMessage = + NotificationMessage.toAllUserLunchEventNotificationContent(); + + if (receiver.getDeviceToken() != null && !Objects.equals(receiver.getDeviceToken(), + "")) { + final Message message = + fcmManager.createMessage(receiver.getDeviceToken(), notificationMessage); + fcmManager.send(message); + + } + } } diff --git a/src/main/java/com/yello/server/infrastructure/firebase/service/NotificationService.java b/src/main/java/com/yello/server/infrastructure/firebase/service/NotificationService.java index b0d8f687..0ebd7cc2 100644 --- a/src/main/java/com/yello/server/infrastructure/firebase/service/NotificationService.java +++ b/src/main/java/com/yello/server/infrastructure/firebase/service/NotificationService.java @@ -6,6 +6,8 @@ import com.yello.server.global.common.dto.EmptyObject; import com.yello.server.infrastructure.firebase.dto.request.NotificationCustomMessage; +import java.util.List; + public interface NotificationService { void sendRecommendNotification(User user, User target); @@ -19,4 +21,5 @@ public interface NotificationService { void sendCustomNotification(NotificationCustomMessage request); EmptyObject adminSendCustomNotification(Long adminId, NotificationCustomMessage request); + void sendLunchEventNotification(User userList); } From f2b6438341a7d5ecfd7334f6ee4b731e84258373 Mon Sep 17 00:00:00 2001 From: hyeonjeongs Date: Mon, 26 Feb 2024 17:25:43 +0900 Subject: [PATCH 04/16] =?UTF-8?q?YEL-214=20[feat]=20lunch=20event=20spring?= =?UTF-8?q?=20batch,=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); - } } From c895a0b1b6ebe6be9d63dab747c9f4ff72547378 Mon Sep 17 00:00:00 2001 From: hyeonjeongs Date: Wed, 28 Feb 2024 09:50:45 +0900 Subject: [PATCH 05/16] =?UTF-8?q?YEL-214=20[feat]=20=ED=88=AC=ED=91=9C=20?= =?UTF-8?q?=EC=97=B4=EB=9E=8C=EC=8B=9C=20=EB=B3=B4=EB=82=B8=EC=82=AC?= =?UTF-8?q?=EB=9E=8C=EC=97=90=EA=B2=8C=20=ED=91=B8=EC=8B=9C=EC=95=8C?= =?UTF-8?q?=EB=A6=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../server/domain/vote/service/VoteService.java | 6 ++++++ .../firebase/dto/NotificationType.java | 3 ++- .../firebase/dto/request/NotificationMessage.java | 8 ++++++++ .../firebase/service/NotificationFcmService.java | 12 ++++++++++++ .../firebase/service/NotificationService.java | 2 ++ 5 files changed, 30 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/yello/server/domain/vote/service/VoteService.java b/src/main/java/com/yello/server/domain/vote/service/VoteService.java index 7c23eb3b..246aef58 100644 --- a/src/main/java/com/yello/server/domain/vote/service/VoteService.java +++ b/src/main/java/com/yello/server/domain/vote/service/VoteService.java @@ -45,6 +45,7 @@ import com.yello.server.domain.vote.exception.VoteForbiddenException; import com.yello.server.domain.vote.exception.VoteNotFoundException; import com.yello.server.domain.vote.repository.VoteRepository; +import com.yello.server.infrastructure.firebase.service.NotificationService; import com.yello.server.infrastructure.rabbitmq.service.ProducerService; import java.time.LocalDateTime; import java.util.List; @@ -73,6 +74,7 @@ public class VoteService { private final VoteManager voteManager; private final ProducerService producerService; + private final NotificationService notificationService; public VoteListResponse findAllVotes(Long userId, Pageable pageable) { Integer totalCount = voteRepository.countAllByReceiverUserId(userId); @@ -104,6 +106,10 @@ public VoteDetailResponse findVoteById(Long voteId, Long userId) { final Vote vote = voteRepository.getById(voteId); final User user = userRepository.getById(userId); + if(!vote.getIsRead()) { + notificationService.sendOpenVoteNotification(user); + } + vote.read(); return VoteDetailResponse.of(vote, user); } diff --git a/src/main/java/com/yello/server/infrastructure/firebase/dto/NotificationType.java b/src/main/java/com/yello/server/infrastructure/firebase/dto/NotificationType.java index f940b3bd..6ab4a915 100644 --- a/src/main/java/com/yello/server/infrastructure/firebase/dto/NotificationType.java +++ b/src/main/java/com/yello/server/infrastructure/firebase/dto/NotificationType.java @@ -5,5 +5,6 @@ public enum NotificationType { VOTE_AVAILABLE, NEW_FRIEND, RECOMMEND, - LUNCH_EVENT + LUNCH_EVENT, + OPEN_VOTE } diff --git a/src/main/java/com/yello/server/infrastructure/firebase/dto/request/NotificationMessage.java b/src/main/java/com/yello/server/infrastructure/firebase/dto/request/NotificationMessage.java index 430e60a0..baa9063d 100644 --- a/src/main/java/com/yello/server/infrastructure/firebase/dto/request/NotificationMessage.java +++ b/src/main/java/com/yello/server/infrastructure/firebase/dto/request/NotificationMessage.java @@ -52,6 +52,14 @@ public static NotificationMessage toYelloNotificationContent(Vote vote) { .build(); } + public static NotificationMessage toUserOpenVoteNotificationContent(User user) { + return NotificationMessage.builder() + .title(MessageFormat.format("{0}님이 내가 보낸 쪽지를 확인했어요! ", user.getName())) + .message("\uD83D\uDEA8\uD83D\uDC9A 그린라이트입니다.") + .type(NotificationType.OPEN_VOTE) + .build(); + } + public static NotificationMessage toAllUserLunchEventNotificationContent() { return NotificationMessage.builder() .title("우리 학교 선착순 30명 열람권 뿌린다!") diff --git a/src/main/java/com/yello/server/infrastructure/firebase/service/NotificationFcmService.java b/src/main/java/com/yello/server/infrastructure/firebase/service/NotificationFcmService.java index c4d1a6cc..9295d2de 100644 --- a/src/main/java/com/yello/server/infrastructure/firebase/service/NotificationFcmService.java +++ b/src/main/java/com/yello/server/infrastructure/firebase/service/NotificationFcmService.java @@ -133,4 +133,16 @@ public void sendLunchEventNotification(User user) { } } + + @Override + public void sendOpenVoteNotification(User user) { + NotificationMessage notificationMessage = + NotificationMessage.toUserOpenVoteNotificationContent(user); + + if (user.getDeviceToken() != null && !Objects.equals(user.getDeviceToken(), "")) { + final Message message = + fcmManager.createMessage(user.getDeviceToken(), notificationMessage); + fcmManager.send(message); + } + } } diff --git a/src/main/java/com/yello/server/infrastructure/firebase/service/NotificationService.java b/src/main/java/com/yello/server/infrastructure/firebase/service/NotificationService.java index 0ebd7cc2..040c2889 100644 --- a/src/main/java/com/yello/server/infrastructure/firebase/service/NotificationService.java +++ b/src/main/java/com/yello/server/infrastructure/firebase/service/NotificationService.java @@ -22,4 +22,6 @@ public interface NotificationService { EmptyObject adminSendCustomNotification(Long adminId, NotificationCustomMessage request); void sendLunchEventNotification(User userList); + + void sendOpenVoteNotification(User user); } From d8b09d024e75f0ac2b61dfb54544737f892cfd66 Mon Sep 17 00:00:00 2001 From: hyeonjeongs Date: Wed, 28 Feb 2024 09:56:47 +0900 Subject: [PATCH 06/16] =?UTF-8?q?YEL-214=20[fix]=20=EC=98=A4=EB=A5=98=20?= =?UTF-8?q?=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yello/server/domain/user/repository/UserJpaRepository.java | 2 ++ .../com/yello/server/domain/user/repository/UserRepository.java | 2 ++ 2 files changed, 4 insertions(+) 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 35fc50e2..8025c131 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,5 +134,7 @@ 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 0c9d9256..c57e9e6a 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,4 +76,6 @@ List findAllByOtherGroupContainingYelloId(String groupName, String keyword void delete(User user); + Page findAllByPageable(Pageable pageable); + } From a888fe57fc6e9a0aa58d8b67f42215d20b1ab34c Mon Sep 17 00:00:00 2001 From: hyeonjeongs Date: Wed, 28 Feb 2024 10:08:37 +0900 Subject: [PATCH 07/16] =?UTF-8?q?YEL-214=20[fix]=20=ED=88=AC=ED=91=9C?= =?UTF-8?q?=EC=8B=9C=20=EA=B0=91=EC=9E=90=EA=B8=B0=20=ED=83=88=ED=87=B4?= =?UTF-8?q?=ED=95=9C=20=ED=9A=8C=EC=9B=90=20=ED=88=AC=ED=91=9C=EB=8A=94=20?= =?UTF-8?q?=EB=B0=98=EC=98=81=EB=90=98=EC=A7=80=20=EC=95=8A=EB=8F=84?= =?UTF-8?q?=EB=A1=9D=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/vote/service/VoteManagerImpl.java | 143 +++++++++--------- 1 file changed, 68 insertions(+), 75 deletions(-) diff --git a/src/main/java/com/yello/server/domain/vote/service/VoteManagerImpl.java b/src/main/java/com/yello/server/domain/vote/service/VoteManagerImpl.java index 37c79d98..a752daf9 100644 --- a/src/main/java/com/yello/server/domain/vote/service/VoteManagerImpl.java +++ b/src/main/java/com/yello/server/domain/vote/service/VoteManagerImpl.java @@ -1,19 +1,5 @@ package com.yello.server.domain.vote.service; -import static com.yello.server.global.common.ErrorCode.DUPLICATE_VOTE_EXCEPTION; -import static com.yello.server.global.common.ErrorCode.INVALID_VOTE_EXCEPTION; -import static com.yello.server.global.common.ErrorCode.LACK_POINT_EXCEPTION; -import static com.yello.server.global.common.ErrorCode.LACK_USER_EXCEPTION; -import static com.yello.server.global.common.factory.WeightedRandomFactory.randomPoint; -import static com.yello.server.global.common.util.ConstantUtil.KEYWORD_HINT_POINT; -import static com.yello.server.global.common.util.ConstantUtil.NAME_HINT_DEFAULT; -import static com.yello.server.global.common.util.ConstantUtil.NAME_HINT_POINT; -import static com.yello.server.global.common.util.ConstantUtil.NO_FRIEND_COUNT; -import static com.yello.server.global.common.util.ConstantUtil.RANDOM_COUNT; -import static com.yello.server.global.common.util.ConstantUtil.VOTE_COUNT; -import static com.yello.server.global.common.util.ConstantUtil.YELLO_FEMALE; -import static com.yello.server.global.common.util.ConstantUtil.YELLO_MALE; - import com.yello.server.domain.friend.dto.response.FriendShuffleResponse; import com.yello.server.domain.friend.entity.Friend; import com.yello.server.domain.friend.exception.FriendException; @@ -33,17 +19,19 @@ import com.yello.server.domain.vote.exception.VoteForbiddenException; import com.yello.server.domain.vote.exception.VoteNotFoundException; import com.yello.server.domain.vote.repository.VoteRepository; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.concurrent.ThreadLocalRandom; -import java.util.stream.IntStream; import lombok.Builder; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Transactional; +import java.util.*; +import java.util.concurrent.ThreadLocalRandom; +import java.util.stream.IntStream; + +import static com.yello.server.global.common.ErrorCode.*; +import static com.yello.server.global.common.factory.WeightedRandomFactory.randomPoint; +import static com.yello.server.global.common.util.ConstantUtil.*; + @Builder @Component @RequiredArgsConstructor @@ -66,27 +54,32 @@ public List createVotes(Long senderId, List voteAnswers) { final User sender = userRepository.getById(senderId); IntStream.range(0, voteAnswers.size()) - .forEach(index -> { - VoteAnswer currentVote = voteAnswers.get(index); + .filter(index -> { + User receiver = userRepository.getById(voteAnswers.get(index).friendId()); + return Objects.isNull(receiver.getDeletedAt()); + }) + .forEach(index -> { + VoteAnswer currentVote = voteAnswers.get(index); + + if (isDuplicatedVote(index, voteAnswers)) { + throw new VoteForbiddenException(DUPLICATE_VOTE_EXCEPTION); + } - if (isDuplicatedVote(index, voteAnswers)) { - throw new VoteForbiddenException(DUPLICATE_VOTE_EXCEPTION); - } + User receiver = userRepository.getById(currentVote.friendId()); + Question question = questionRepository.getById(currentVote.questionId()); - User receiver = userRepository.getById(currentVote.friendId()); - Question question = questionRepository.getById(currentVote.questionId()); - Vote newVote = Vote.createVote( - currentVote.keywordName(), - sender, - receiver, - question, - currentVote.colorIndex() - ); + Vote newVote = Vote.createVote( + currentVote.keywordName(), + sender, + receiver, + question, + currentVote.colorIndex() + ); - Vote savedVote = voteRepository.save(newVote); - votes.add(savedVote); - }); + Vote savedVote = voteRepository.save(newVote); + votes.add(savedVote); + }); return votes; } @@ -97,15 +90,15 @@ public List generateVoteQuestion(User user, List QuestionForVoteResponse.builder() - .friendList(getShuffledFriends(user)) - .keywordList(getShuffledKeywords(question)) - .question(QuestionVO.of(question)) - .questionPoint(randomPoint()) - .subscribe(user.getSubscribe().toString()) - .build()) - .limit(VOTE_COUNT) - .toList(); + .map(question -> QuestionForVoteResponse.builder() + .friendList(getShuffledFriends(user)) + .keywordList(getShuffledKeywords(question)) + .question(QuestionVO.of(question)) + .questionPoint(randomPoint()) + .subscribe(user.getSubscribe().toString()) + .build()) + .limit(VOTE_COUNT) + .toList(); } @Override @@ -146,18 +139,18 @@ public KeywordCheckResponse useKeywordHint(User user, Vote vote) { public void makeGreetingVote(User user) { final User sender = userManager.getOfficialUser(user.getGender()); final Question greetingQuestion = questionRepository.findByQuestionContent( - null, - GREETING_NAME_FOOT, - null, - GREETING_KEYWORD_FOOT + null, + GREETING_NAME_FOOT, + null, + GREETING_KEYWORD_FOOT ).orElseGet(() -> - questionRepository.save( - Question.of( - null, - GREETING_NAME_FOOT, - null, - GREETING_KEYWORD_FOOT) - ) + questionRepository.save( + Question.of( + null, + GREETING_NAME_FOOT, + null, + GREETING_KEYWORD_FOOT) + ) ); voteRepository.save(createFirstVote(sender, user, greetingQuestion)); @@ -177,19 +170,19 @@ public List getShuffledFriends(User user) { if (friends.size() > NO_FRIEND_COUNT && friends.size() < RANDOM_COUNT) { return friendList.stream() - .map(FriendShuffleResponse::of) - .toList(); + .map(FriendShuffleResponse::of) + .toList(); } return friendList.stream() - .map(FriendShuffleResponse::of) - .limit(RANDOM_COUNT) - .toList(); + .map(FriendShuffleResponse::of) + .limit(RANDOM_COUNT) + .toList(); } private boolean isDuplicatedVote(int index, List voteAnswers) { return index > 0 && voteAnswers.get(index - 1).questionId() - .equals(voteAnswers.get(index).questionId()); + .equals(voteAnswers.get(index).questionId()); } private List getShuffledKeywords(Question question) { @@ -198,9 +191,9 @@ private List getShuffledKeywords(Question question) { Collections.shuffle(keywordList); return keywordList.stream() - .map(Keyword::getKeywordName) - .limit(RANDOM_COUNT) - .toList(); + .map(Keyword::getKeywordName) + .limit(RANDOM_COUNT) + .toList(); } private Vote createFirstVote(User sender, User receiver, Question question) { @@ -208,14 +201,14 @@ private Vote createFirstVote(User sender, User receiver, Question question) { final String answer = "널 기다렸어"; return Vote.builder() - .answer(answer) - .nameHint(-3) - .isAnswerRevealed(true) - .isRead(false) - .sender(sender) - .receiver(receiver) - .question(question) - .colorIndex(random.nextInt(12) + 1) - .build(); + .answer(answer) + .nameHint(-3) + .isAnswerRevealed(true) + .isRead(false) + .sender(sender) + .receiver(receiver) + .question(question) + .colorIndex(random.nextInt(12) + 1) + .build(); } } From 2996d45a3a1065f4ddd72224b15bc2e81b636529 Mon Sep 17 00:00:00 2001 From: hyeonjeongs Date: Wed, 28 Feb 2024 10:14:55 +0900 Subject: [PATCH 08/16] YEL-214 [fix] vote repository --- .../yello/server/domain/user/repository/UserJpaRepository.java | 1 + 1 file changed, 1 insertion(+) 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 8025c131..23eb288d 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,7 @@ List findAllByOtherGroupContainingYelloId(@Param("groupName") String group + "where LOWER(u.name) like LOWER(CONCAT('%', :name, '%'))") Page findAllByNameContaining(Pageable pageable, @Param("name") String name); + @Query("select u from User u") Page findAllByPageable(Pageable pageable); From daa06e8bade4ad314df91527839355f9847189fb Mon Sep 17 00:00:00 2001 From: hyeonjeongs Date: Wed, 28 Feb 2024 10:18:39 +0900 Subject: [PATCH 09/16] YEL-214 [fix] vote repository --- .../server/domain/user/repository/UserJpaRepository.java | 4 ---- .../yello/server/domain/user/repository/UserRepository.java | 2 -- .../server/domain/user/repository/UserRepositoryImpl.java | 5 +---- 3 files changed, 1 insertion(+), 10 deletions(-) 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 23eb288d..5e6d6df7 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,8 +134,4 @@ List findAllByOtherGroupContainingYelloId(@Param("groupName") String group + "where LOWER(u.name) like LOWER(CONCAT('%', :name, '%'))") Page findAllByNameContaining(Pageable pageable, @Param("name") String name); - @Query("select u from User u") - 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 c57e9e6a..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,6 +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/domain/user/repository/UserRepositoryImpl.java b/src/main/java/com/yello/server/domain/user/repository/UserRepositoryImpl.java index d7acebae..7a9a85af 100644 --- a/src/main/java/com/yello/server/domain/user/repository/UserRepositoryImpl.java +++ b/src/main/java/com/yello/server/domain/user/repository/UserRepositoryImpl.java @@ -193,8 +193,5 @@ public void delete(User user) { userJpaRepository.delete(user); } - @Override - public Page findAllByPageable(Pageable pageable) { - return userJpaRepository.findAllByPageable(pageable); - } + } From 4b4a5c46e8dea01d68ad416dd58f023aea9ebbb2 Mon Sep 17 00:00:00 2001 From: hyeonjeongs Date: Wed, 28 Feb 2024 10:30:21 +0900 Subject: [PATCH 10/16] =?UTF-8?q?YEL-214=20[fix]=20vote=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/request/NotificationMessage.java | 10 +- .../domain/vote/small/VoteServiceTest.java | 109 +++++++++--------- 2 files changed, 64 insertions(+), 55 deletions(-) diff --git a/src/main/java/com/yello/server/infrastructure/firebase/dto/request/NotificationMessage.java b/src/main/java/com/yello/server/infrastructure/firebase/dto/request/NotificationMessage.java index baa9063d..7eca37a3 100644 --- a/src/main/java/com/yello/server/infrastructure/firebase/dto/request/NotificationMessage.java +++ b/src/main/java/com/yello/server/infrastructure/firebase/dto/request/NotificationMessage.java @@ -54,12 +54,20 @@ public static NotificationMessage toYelloNotificationContent(Vote vote) { public static NotificationMessage toUserOpenVoteNotificationContent(User user) { return NotificationMessage.builder() - .title(MessageFormat.format("{0}님이 내가 보낸 쪽지를 확인했어요! ", user.getName())) + .title(MessageFormat.format("{0}님이 내가 보낸 쪽지를 확인했어요!", user.getName())) .message("\uD83D\uDEA8\uD83D\uDC9A 그린라이트입니다.") .type(NotificationType.OPEN_VOTE) .build(); } + public static NotificationMessage toUserAndFriendRecommendSignupNotificationContent(User user) { + return NotificationMessage.builder() + .title(MessageFormat.format("{0}님이 나를 추천인으로 가입해 열람권이 지급됐어요!", user.getName())) + .message("지금이다! 날 짝사랑 하는 사람 보러가기") + .type(NotificationType.OPEN_VOTE) + .build(); + } + public static NotificationMessage toAllUserLunchEventNotificationContent() { return NotificationMessage.builder() .title("우리 학교 선착순 30명 열람권 뿌린다!") diff --git a/src/test/java/com/yello/server/domain/vote/small/VoteServiceTest.java b/src/test/java/com/yello/server/domain/vote/small/VoteServiceTest.java index 1d096ebf..36cd3d6c 100644 --- a/src/test/java/com/yello/server/domain/vote/small/VoteServiceTest.java +++ b/src/test/java/com/yello/server/domain/vote/small/VoteServiceTest.java @@ -1,8 +1,5 @@ package com.yello.server.domain.vote.small; -import static com.yello.server.global.common.factory.PaginationFactory.createPageable; -import static org.assertj.core.api.Assertions.assertThat; - import com.yello.server.domain.cooldown.FakeCooldownRepository; import com.yello.server.domain.cooldown.repository.CooldownRepository; import com.yello.server.domain.friend.FakeFriendRepository; @@ -36,32 +33,30 @@ import com.yello.server.domain.vote.FakeVoteRepository; import com.yello.server.domain.vote.dto.request.CreateVoteRequest; import com.yello.server.domain.vote.dto.request.VoteAnswer; -import com.yello.server.domain.vote.dto.response.RevealNameResponse; -import com.yello.server.domain.vote.dto.response.VoteAvailableResponse; -import com.yello.server.domain.vote.dto.response.VoteCreateVO; -import com.yello.server.domain.vote.dto.response.VoteDetailResponse; -import com.yello.server.domain.vote.dto.response.VoteFriendResponse; -import com.yello.server.domain.vote.dto.response.VoteListResponse; -import com.yello.server.domain.vote.dto.response.VoteUnreadCountResponse; +import com.yello.server.domain.vote.dto.response.*; import com.yello.server.domain.vote.entity.Vote; import com.yello.server.domain.vote.repository.VoteRepository; import com.yello.server.domain.vote.service.VoteManager; import com.yello.server.domain.vote.service.VoteService; +import com.yello.server.infrastructure.firebase.FakeFcmManger; +import com.yello.server.infrastructure.firebase.manager.FCMManager; +import com.yello.server.infrastructure.firebase.service.NotificationFcmService; +import com.yello.server.infrastructure.firebase.service.NotificationService; import com.yello.server.infrastructure.rabbitmq.FakeMessageQueueRepository; import com.yello.server.infrastructure.rabbitmq.FakeProducerService; import com.yello.server.infrastructure.rabbitmq.service.ProducerService; import com.yello.server.util.TestDataEntityUtil; import com.yello.server.util.TestDataRepositoryUtil; -import java.util.ArrayList; -import java.util.List; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.DisplayNameGeneration; +import org.junit.jupiter.api.*; import org.junit.jupiter.api.DisplayNameGenerator.ReplaceUnderscores; -import org.junit.jupiter.api.Test; import org.springframework.data.domain.Pageable; +import java.util.ArrayList; +import java.util.List; + +import static com.yello.server.global.common.factory.PaginationFactory.createPageable; +import static org.assertj.core.api.Assertions.assertThat; + @DisplayName("VoteService 에서") @DisplayNameGeneration(ReplaceUnderscores.class) public class VoteServiceTest { @@ -71,35 +66,40 @@ public class VoteServiceTest { private final KeywordRepository keywordRepository = new FakeKeywordRepository(); private final NoticeRepository noticeRepository = new FakeNoticeRepository(); private final ProducerService producerService = - new FakeProducerService(new FakeMessageQueueRepository()); + new FakeProducerService(new FakeMessageQueueRepository()); private final PurchaseRepository purchaseRepository = new FakePurchaseRepository(); private final QuestionRepository questionRepository = new FakeQuestionRepository(); private final QuestionGroupTypeRepository questionGroupTypeRepository = new FakeQuestionGroupTypeRepository( - questionRepository); + questionRepository); private final TestDataEntityUtil testDataEntityUtil = new TestDataEntityUtil(); private final UserDataRepository userDataRepository = new FakeUserDataRepository(); private final UserGroupRepository userGroupRepository = new FakeUserGroupRepository(); private final UserRepository userRepository = new FakeUserRepository(friendRepository); private final UserManager userManager = new FakeUserManager(userRepository); + private final FCMManager fcmManager = new FakeFcmManger(); + private final NotificationService notificationService = NotificationFcmService.builder() + .userRepository(userRepository) + .fcmManager(fcmManager) + .build(); private final VoteRepository voteRepository = new FakeVoteRepository(); private final VoteManager voteManager = new FakeVoteManager( - userRepository, - questionRepository, - voteRepository, - friendRepository, - userManager + userRepository, + questionRepository, + voteRepository, + friendRepository, + userManager ); private final TestDataRepositoryUtil testDataUtil = new TestDataRepositoryUtil( - friendRepository, - noticeRepository, - purchaseRepository, - questionGroupTypeRepository, - questionRepository, - testDataEntityUtil, - userDataRepository, - userGroupRepository, - userRepository, - voteRepository + friendRepository, + noticeRepository, + purchaseRepository, + questionGroupTypeRepository, + questionRepository, + testDataEntityUtil, + userDataRepository, + userGroupRepository, + userRepository, + voteRepository ); private VoteService voteService; private List questionData = new ArrayList<>(); @@ -109,16 +109,17 @@ public class VoteServiceTest { @BeforeEach void init() { this.voteService = VoteService.builder() - .voteRepository(voteRepository) - .friendRepository(friendRepository) - .cooldownRepository(cooldownRepository) - .userRepository(userRepository) - .questionRepository(questionRepository) - .keywordRepository(keywordRepository) - .producerService(producerService) - .voteManager(voteManager) - .questionGroupTypeRepository(questionGroupTypeRepository) - .build(); + .voteRepository(voteRepository) + .friendRepository(friendRepository) + .cooldownRepository(cooldownRepository) + .userRepository(userRepository) + .questionRepository(questionRepository) + .keywordRepository(keywordRepository) + .producerService(producerService) + .voteManager(voteManager) + .questionGroupTypeRepository(questionGroupTypeRepository) + .notificationService(notificationService) + .build(); for (long i = 1; i <= 8; i++) { questionData.add(testDataUtil.generateQuestion(i)); @@ -126,7 +127,7 @@ void init() { for (long i = 1; i <= 8; i++) { QuestionGroupType questionGroupType = testDataUtil.generateQuestionGroupType(i, - questionData.get(Long.valueOf(i).intValue() - 1)); + questionData.get(Long.valueOf(i).intValue() - 1)); questionGroupTypeData.add(questionGroupType); } @@ -203,7 +204,7 @@ void cleanup() { // when VoteFriendResponse result = - voteService.findAllFriendVotes(userId, pageable); // 다시 확인 !! + voteService.findAllFriendVotes(userId, pageable); // 다시 확인 !! // then assertThat(result.totalCount()).isEqualTo(4); @@ -262,17 +263,17 @@ void cleanup() { final List voteAnswerList = new ArrayList<>(); VoteAnswer answer1 = VoteAnswer.builder() - .friendId(2L) - .questionId(1L) - .keywordName("test") - .colorIndex(0) - .build(); + .friendId(2L) + .questionId(1L) + .keywordName("test") + .colorIndex(0) + .build(); voteAnswerList.add(answer1); CreateVoteRequest request = CreateVoteRequest.builder() - .voteAnswerList(voteAnswerList) - .totalPoint(3) - .build(); + .voteAnswerList(voteAnswerList) + .totalPoint(3) + .build(); // when VoteCreateVO result = voteService.createVote(userId, request); From 01f65cadb950ce0ffcbb7e9a19d77b63703a92e0 Mon Sep 17 00:00:00 2001 From: hyeonjeongs Date: Wed, 28 Feb 2024 10:39:11 +0900 Subject: [PATCH 11/16] =?UTF-8?q?YEL-214=20[feat]=20=EC=B6=94=EC=B2=9C?= =?UTF-8?q?=EC=9D=B8=EC=BD=94=EB=93=9C=20=EA=B0=80=EC=9E=85=EC=8B=9C=20?= =?UTF-8?q?=EC=97=B4=EB=9E=8C=EA=B6=8C=20=EC=A7=80=EA=B8=89=20=ED=91=B8?= =?UTF-8?q?=EC=8B=9C=EC=95=8C=EB=A6=BC=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/authorization/service/AuthService.java | 1 + .../firebase/dto/request/NotificationMessage.java | 2 +- .../firebase/service/NotificationFcmService.java | 12 ++++++++++++ .../firebase/service/NotificationService.java | 2 ++ 4 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/yello/server/domain/authorization/service/AuthService.java b/src/main/java/com/yello/server/domain/authorization/service/AuthService.java index 40140383..709ec931 100644 --- a/src/main/java/com/yello/server/domain/authorization/service/AuthService.java +++ b/src/main/java/com/yello/server/domain/authorization/service/AuthService.java @@ -127,6 +127,7 @@ public void recommendUser(String recommendYelloId, String userYelloId) { ZonedDateTime.now(GlobalZoneId).format(ISO_OFFSET_DATE_TIME), recommendedUser )); + notificationService.sendRecommendSignupNotification(recommendedUser); } notificationService.sendRecommendNotification(user, recommendedUser); diff --git a/src/main/java/com/yello/server/infrastructure/firebase/dto/request/NotificationMessage.java b/src/main/java/com/yello/server/infrastructure/firebase/dto/request/NotificationMessage.java index 7eca37a3..44f0ccdc 100644 --- a/src/main/java/com/yello/server/infrastructure/firebase/dto/request/NotificationMessage.java +++ b/src/main/java/com/yello/server/infrastructure/firebase/dto/request/NotificationMessage.java @@ -64,7 +64,7 @@ public static NotificationMessage toUserAndFriendRecommendSignupNotificationCont return NotificationMessage.builder() .title(MessageFormat.format("{0}님이 나를 추천인으로 가입해 열람권이 지급됐어요!", user.getName())) .message("지금이다! 날 짝사랑 하는 사람 보러가기") - .type(NotificationType.OPEN_VOTE) + .type(NotificationType.RECOMMEND) .build(); } diff --git a/src/main/java/com/yello/server/infrastructure/firebase/service/NotificationFcmService.java b/src/main/java/com/yello/server/infrastructure/firebase/service/NotificationFcmService.java index 9295d2de..f6939020 100644 --- a/src/main/java/com/yello/server/infrastructure/firebase/service/NotificationFcmService.java +++ b/src/main/java/com/yello/server/infrastructure/firebase/service/NotificationFcmService.java @@ -145,4 +145,16 @@ public void sendOpenVoteNotification(User user) { fcmManager.send(message); } } + + @Override + public void sendRecommendSignupNotification(User recommendUser) { + NotificationMessage notificationMessage = + NotificationMessage.toUserAndFriendRecommendSignupNotificationContent(recommendUser); + + if (recommendUser.getDeviceToken() != null && !Objects.equals(recommendUser.getDeviceToken(), "")) { + final Message message = + fcmManager.createMessage(recommendUser.getDeviceToken(), notificationMessage); + fcmManager.send(message); + } + } } diff --git a/src/main/java/com/yello/server/infrastructure/firebase/service/NotificationService.java b/src/main/java/com/yello/server/infrastructure/firebase/service/NotificationService.java index 040c2889..83a5bd07 100644 --- a/src/main/java/com/yello/server/infrastructure/firebase/service/NotificationService.java +++ b/src/main/java/com/yello/server/infrastructure/firebase/service/NotificationService.java @@ -24,4 +24,6 @@ public interface NotificationService { void sendLunchEventNotification(User userList); void sendOpenVoteNotification(User user); + + void sendRecommendSignupNotification(User user); } From 4b94592aef030545d7de916ebadeebe0b039f8fa Mon Sep 17 00:00:00 2001 From: hyeonjeongs Date: Wed, 28 Feb 2024 10:54:19 +0900 Subject: [PATCH 12/16] =?UTF-8?q?YEL-214=20[feat]=20=ED=91=B8=EC=8B=9C?= =?UTF-8?q?=EC=95=8C=EB=A6=BC=20=EA=B5=AC=ED=98=84=20=EB=B0=8F=20unit=20te?= =?UTF-8?q?st?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../authorization/service/AuthService.java | 2 +- .../domain/vote/service/VoteService.java | 2 +- .../dto/request/NotificationMessage.java | 2 +- .../service/NotificationFcmService.java | 12 +++---- .../firebase/service/NotificationService.java | 4 +-- .../firebase/NotificationFcmServiceTest.java | 36 ++++++++++++++++++- 6 files changed, 45 insertions(+), 13 deletions(-) diff --git a/src/main/java/com/yello/server/domain/authorization/service/AuthService.java b/src/main/java/com/yello/server/domain/authorization/service/AuthService.java index 709ec931..d995dd79 100644 --- a/src/main/java/com/yello/server/domain/authorization/service/AuthService.java +++ b/src/main/java/com/yello/server/domain/authorization/service/AuthService.java @@ -127,7 +127,7 @@ public void recommendUser(String recommendYelloId, String userYelloId) { ZonedDateTime.now(GlobalZoneId).format(ISO_OFFSET_DATE_TIME), recommendedUser )); - notificationService.sendRecommendSignupNotification(recommendedUser); + notificationService.sendRecommendSignupAndGetTicketNotification(recommendedUser); } notificationService.sendRecommendNotification(user, recommendedUser); diff --git a/src/main/java/com/yello/server/domain/vote/service/VoteService.java b/src/main/java/com/yello/server/domain/vote/service/VoteService.java index 246aef58..afcdc96a 100644 --- a/src/main/java/com/yello/server/domain/vote/service/VoteService.java +++ b/src/main/java/com/yello/server/domain/vote/service/VoteService.java @@ -107,7 +107,7 @@ public VoteDetailResponse findVoteById(Long voteId, Long userId) { final User user = userRepository.getById(userId); if(!vote.getIsRead()) { - notificationService.sendOpenVoteNotification(user); + notificationService.sendOpenVoteNotification(vote.getSender()); } vote.read(); diff --git a/src/main/java/com/yello/server/infrastructure/firebase/dto/request/NotificationMessage.java b/src/main/java/com/yello/server/infrastructure/firebase/dto/request/NotificationMessage.java index 44f0ccdc..00b0204f 100644 --- a/src/main/java/com/yello/server/infrastructure/firebase/dto/request/NotificationMessage.java +++ b/src/main/java/com/yello/server/infrastructure/firebase/dto/request/NotificationMessage.java @@ -60,7 +60,7 @@ public static NotificationMessage toUserOpenVoteNotificationContent(User user) { .build(); } - public static NotificationMessage toUserAndFriendRecommendSignupNotificationContent(User user) { + public static NotificationMessage toUserAndFriendRecommendSignupAndGetTicketNotificationContent(User user) { return NotificationMessage.builder() .title(MessageFormat.format("{0}님이 나를 추천인으로 가입해 열람권이 지급됐어요!", user.getName())) .message("지금이다! 날 짝사랑 하는 사람 보러가기") diff --git a/src/main/java/com/yello/server/infrastructure/firebase/service/NotificationFcmService.java b/src/main/java/com/yello/server/infrastructure/firebase/service/NotificationFcmService.java index f6939020..58aa485c 100644 --- a/src/main/java/com/yello/server/infrastructure/firebase/service/NotificationFcmService.java +++ b/src/main/java/com/yello/server/infrastructure/firebase/service/NotificationFcmService.java @@ -135,21 +135,21 @@ public void sendLunchEventNotification(User user) { } @Override - public void sendOpenVoteNotification(User user) { + public void sendOpenVoteNotification(User sender) { NotificationMessage notificationMessage = - NotificationMessage.toUserOpenVoteNotificationContent(user); + NotificationMessage.toUserOpenVoteNotificationContent(sender); - if (user.getDeviceToken() != null && !Objects.equals(user.getDeviceToken(), "")) { + if (sender.getDeviceToken() != null && !Objects.equals(sender.getDeviceToken(), "")) { final Message message = - fcmManager.createMessage(user.getDeviceToken(), notificationMessage); + fcmManager.createMessage(sender.getDeviceToken(), notificationMessage); fcmManager.send(message); } } @Override - public void sendRecommendSignupNotification(User recommendUser) { + public void sendRecommendSignupAndGetTicketNotification(User recommendUser) { NotificationMessage notificationMessage = - NotificationMessage.toUserAndFriendRecommendSignupNotificationContent(recommendUser); + NotificationMessage.toUserAndFriendRecommendSignupAndGetTicketNotificationContent(recommendUser); if (recommendUser.getDeviceToken() != null && !Objects.equals(recommendUser.getDeviceToken(), "")) { final Message message = diff --git a/src/main/java/com/yello/server/infrastructure/firebase/service/NotificationService.java b/src/main/java/com/yello/server/infrastructure/firebase/service/NotificationService.java index 83a5bd07..e613b4aa 100644 --- a/src/main/java/com/yello/server/infrastructure/firebase/service/NotificationService.java +++ b/src/main/java/com/yello/server/infrastructure/firebase/service/NotificationService.java @@ -6,8 +6,6 @@ import com.yello.server.global.common.dto.EmptyObject; import com.yello.server.infrastructure.firebase.dto.request.NotificationCustomMessage; -import java.util.List; - public interface NotificationService { void sendRecommendNotification(User user, User target); @@ -25,5 +23,5 @@ public interface NotificationService { void sendOpenVoteNotification(User user); - void sendRecommendSignupNotification(User user); + void sendRecommendSignupAndGetTicketNotification(User user); } diff --git a/src/test/java/com/yello/server/infrastructure/firebase/NotificationFcmServiceTest.java b/src/test/java/com/yello/server/infrastructure/firebase/NotificationFcmServiceTest.java index 9cde6837..a650f5b1 100644 --- a/src/test/java/com/yello/server/infrastructure/firebase/NotificationFcmServiceTest.java +++ b/src/test/java/com/yello/server/infrastructure/firebase/NotificationFcmServiceTest.java @@ -36,7 +36,8 @@ class NotificationFcmServiceTest { private User user; private User target; private User dummy; - + private Vote vote; + private Question question; @BeforeEach void init() { this.notificationService = NotificationFcmService.builder() @@ -74,6 +75,19 @@ void init() { .deletedAt(null).group(userGroup) .groupAdmissionYear(19).email("yello@test.com") .build(); + question = Question.builder() + .id(1L) + .nameHead(null).nameFoot("와") + .keywordHead("멋진").keywordFoot("에서 놀고싶어") + .build(); + vote = Vote.builder() + .id(1L) + .colorIndex(0).answer("test") + .isRead(false).nameHint(-1).isAnswerRevealed(false) + .sender(userRepository.getById(1L)) + .receiver(userRepository.getById(2L)) + .question(question).createdAt(LocalDateTime.now()) + .build(); } @Test @@ -120,6 +134,26 @@ void init() { notificationService.sendFriendNotification(friend); } + @Test + void 친구가_내가_보낸_쪽지_열람시_알림_전송에_성공합니다() { + //given + target.setDeviceToken("test-device-token"); + + // when + // then + notificationService.sendOpenVoteNotification(vote.getSender()); + } + + @Test + void 추천인_코드_가입하여_열람권_얻은_경우_알림_전송에_성공합니다() { + //given + target.setDeviceToken("test-device-token"); + + // when + // then + notificationService.sendRecommendSignupAndGetTicketNotification(target); + } + @Test void 푸시_알림_전송_시_존재하지_않는_유저인_경우에_UserNotFoundException이_발생합니다() { // given From a127d977b00d8c09241ffdae3a75d31b692f01b6 Mon Sep 17 00:00:00 2001 From: hyeonjeongs Date: Thu, 29 Feb 2024 02:29:09 +0900 Subject: [PATCH 13/16] =?UTF-8?q?YEL-214=20[setting]=20YEL-214=20[fix]=20?= =?UTF-8?q?=EC=8A=A4=ED=94=84=EB=A7=81=20=EB=B0=B0=EC=B9=98=EC=9D=B4?= =?UTF-8?q?=EC=8A=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../infrastructure/batch/ChunkProcessor.java | 9 +++ .../infrastructure/batch/ChunkReader.java | 63 +++++++++++-------- .../batch/StepConfiguration.java | 18 +++--- .../service/NotificationFcmService.java | 1 + .../scheduler/EventScheduler.java | 8 ++- 5 files changed, 61 insertions(+), 38 deletions(-) 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 4fc93ecd..7159f88c 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,20 @@ package com.yello.server.infrastructure.batch; +import com.yello.server.domain.user.entity.User; import lombok.RequiredArgsConstructor; +import org.springframework.batch.item.ItemProcessor; import org.springframework.context.annotation.Configuration; @RequiredArgsConstructor @Configuration public class ChunkProcessor { + public ItemProcessor lunchEventProcessor() { + ItemProcessor item = user -> { + System.out.println(user.getId() + ", "+ user.getName() + " dds121212"); + return user; + }; + return item; + } } 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 3a777cd2..0cf181f2 100644 --- a/src/main/java/com/yello/server/infrastructure/batch/ChunkReader.java +++ b/src/main/java/com/yello/server/infrastructure/batch/ChunkReader.java @@ -3,14 +3,18 @@ import com.yello.server.domain.user.entity.User; import com.yello.server.domain.user.repository.UserJpaRepository; import jakarta.persistence.EntityManagerFactory; +import java.util.Collections; +import javax.sql.DataSource; 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.JdbcCursorItemReader; 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.JdbcCursorItemReaderBuilder; import org.springframework.batch.item.database.builder.JdbcPagingItemReaderBuilder; import org.springframework.batch.item.database.builder.JpaPagingItemReaderBuilder; import org.springframework.batch.item.database.support.SqlPagingQueryProviderFactoryBean; @@ -19,14 +23,10 @@ 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; @@ -36,12 +36,22 @@ public class ChunkReader { public RepositoryItemReader usersDataRepositoryItemReader() { return new RepositoryItemReaderBuilder() - .name("userDataReader") - .repository(userRepository) - .methodName("findAllByPageable") - .pageSize(100) - .sorts(Collections.singletonMap("id", Sort.Direction.ASC)) - .build(); + .name("userDataReader") + .repository(userRepository) + .methodName("findAllByPageable") + .pageSize(100) + .sorts(Collections.singletonMap("id", Sort.Direction.ASC)) + .build(); + } + + public JdbcCursorItemReader jdbcCursorItemReader() { + return new JdbcCursorItemReaderBuilder() + .fetchSize(10) + .dataSource(dataSource) + .rowMapper(new BeanPropertyRowMapper<>(User.class)) + .sql("SELECT u.id, u.name FROM user u WHERE u.deleted_at is NULL ORDER BY u.id") + .name("jdbcCursorItemReader") + .build(); } @Bean @@ -49,11 +59,11 @@ public RepositoryItemReader usersDataRepositoryItemReader() { public JpaPagingItemReader userDataJpaPagingItemReader() { return new JpaPagingItemReaderBuilder() - .name("userDataReader") - .pageSize(100) - .queryString("SELECT u FROM USER u ORDER BY id") - .entityManagerFactory(entityManagerFactory) - .build(); + .name("userDataReader") + .pageSize(100) + .queryString("SELECT u FROM USER u ORDER BY id") + .entityManagerFactory(entityManagerFactory) + .build(); } @Bean @@ -61,25 +71,24 @@ public JpaPagingItemReader userDataJpaPagingItemReader() { public JdbcPagingItemReader userDataJdbcPagingItemReader() throws Exception { return new JdbcPagingItemReaderBuilder() - .pageSize(100) - .fetchSize(100) - .dataSource(dataSource) - .rowMapper(new BeanPropertyRowMapper<>(User.class)) - .queryProvider(createUserDataQueryProvider()) - .name("jdbcPagingItemReader") - .build(); + .pageSize(100) + .fetchSize(100) + .dataSource(dataSource) + .queryProvider(createUserDataQueryProvider()) + .rowMapper(new BeanPropertyRowMapper<>(User.class)) + .name("jdbcPagingItemReader") + .build(); } @Bean public PagingQueryProvider createUserDataQueryProvider() throws Exception { SqlPagingQueryProviderFactoryBean queryProvider = new SqlPagingQueryProviderFactoryBean(); queryProvider.setDataSource(dataSource); - queryProvider.setSelectClause("id"); + queryProvider.setSelectClause("*"); queryProvider.setFromClause("from user"); + queryProvider.setWhereClause("where deleted_at is null"); - Map sortKeys = new HashMap<>(); - sortKeys.put("id", Order.ASCENDING); - queryProvider.setSortKeys(sortKeys); + queryProvider.setSortKeys(Collections.singletonMap("id", Order.ASCENDING)); return queryProvider.getObject(); 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 a5746343..f46f6717 100644 --- a/src/main/java/com/yello/server/infrastructure/batch/StepConfiguration.java +++ b/src/main/java/com/yello/server/infrastructure/batch/StepConfiguration.java @@ -1,34 +1,32 @@ package com.yello.server.infrastructure.batch; import com.yello.server.domain.user.entity.User; -import com.yello.server.domain.user.entity.UserData; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.springframework.batch.core.Job; import org.springframework.batch.core.Step; -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.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 @RequiredArgsConstructor @Configuration public class StepConfiguration { + private final ChunkReader chunkReader; private final ChunkProcessor chunkProcessor; private final ChunkWriter chunkWriter; @Bean - public Step lunchEventAlarmStep(JobRepository jobRepository, PlatformTransactionManager transactionManager) throws Exception { + public Step lunchEventAlarmStep(JobRepository jobRepository, + PlatformTransactionManager transactionManager) throws Exception { return new StepBuilder("lunchEventStep", jobRepository) - .chunk(100, transactionManager) - .reader(chunkReader.userDataJdbcPagingItemReader()) - .writer(chunkWriter.lunchEventWriter()) - .build(); + .chunk(10, transactionManager) + .reader(chunkReader.userDataJdbcPagingItemReader()) + .processor(chunkProcessor.lunchEventProcessor()) + .writer(chunkWriter.lunchEventWriter()) + .build(); } } diff --git a/src/main/java/com/yello/server/infrastructure/firebase/service/NotificationFcmService.java b/src/main/java/com/yello/server/infrastructure/firebase/service/NotificationFcmService.java index 58aa485c..0ff43101 100644 --- a/src/main/java/com/yello/server/infrastructure/firebase/service/NotificationFcmService.java +++ b/src/main/java/com/yello/server/infrastructure/firebase/service/NotificationFcmService.java @@ -120,6 +120,7 @@ public EmptyObject adminSendCustomNotification(Long adminId, NotificationCustomM @Override public void sendLunchEventNotification(User user) { + System.out.println(user.getId() + " asfsfsdfsd"); final User receiver = userRepository.getById(user.getId()); NotificationMessage notificationMessage = diff --git a/src/main/java/com/yello/server/infrastructure/scheduler/EventScheduler.java b/src/main/java/com/yello/server/infrastructure/scheduler/EventScheduler.java index 641a4525..729cfa58 100644 --- a/src/main/java/com/yello/server/infrastructure/scheduler/EventScheduler.java +++ b/src/main/java/com/yello/server/infrastructure/scheduler/EventScheduler.java @@ -1,6 +1,10 @@ package com.yello.server.infrastructure.scheduler; +import com.yello.server.domain.user.entity.User; +import com.yello.server.domain.user.entity.UserData; +import com.yello.server.domain.user.entity.UserDataType; +import com.yello.server.domain.user.repository.UserDataRepository; import com.yello.server.infrastructure.batch.JobConfiguration; import lombok.RequiredArgsConstructor; import org.springframework.batch.core.JobParameter; @@ -28,14 +32,16 @@ public class EventScheduler { private final JobConfiguration jobConfiguration; private final JobRepository jobRepository; private final PlatformTransactionManager transactionManager; + private final UserDataRepository userDataRepository; - @Scheduled(cron="0 0 12 * * ?") + @Scheduled(cron="0 19 2 * * ?") public void lunchEventRunJob() { //JobParamter의 역할은 반복해서 실행되는 Job의 유일한 ID임, 동일한 값이 세팅되면 두번째부터 실행안됨) JobParameters jobParameters = new JobParametersBuilder() .addString("uuid", UUID.randomUUID().toString()) .toJobParameters(); + System.out.println("hye!!!!!!!!!!!!"); try { jobLauncher.run(jobConfiguration.lunchEventJob(jobRepository, transactionManager), jobParameters); From 03a9898d3bde98ba4ac1432f384901c6e2f0aae0 Mon Sep 17 00:00:00 2001 From: hyeonjeongs Date: Thu, 29 Feb 2024 10:59:23 +0900 Subject: [PATCH 14/16] =?UTF-8?q?YEL-214=20[feat]=20spring=20batch=20reade?= =?UTF-8?q?r=20=EB=90=98=EC=A7=80=20=EC=95=8A=EB=8A=94=20=EC=9D=B4?= =?UTF-8?q?=EC=8A=88=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 4 +++- .../infrastructure/batch/ChunkProcessor.java | 1 + .../infrastructure/batch/ChunkReader.java | 19 ++++++++++++++++--- .../infrastructure/batch/ChunkWriter.java | 1 + .../batch/JobConfiguration.java | 3 ++- .../batch/StepConfiguration.java | 8 +++++--- .../infrastructure/batch/UserRowMapper.java | 18 ++++++++++++++++++ .../service/NotificationFcmService.java | 1 - .../scheduler/EventScheduler.java | 2 +- 9 files changed, 47 insertions(+), 10 deletions(-) create mode 100644 src/main/java/com/yello/server/infrastructure/batch/UserRowMapper.java diff --git a/build.gradle b/build.gradle index 6a48428a..909410ed 100644 --- a/build.gradle +++ b/build.gradle @@ -48,9 +48,11 @@ dependencies { // Repositories implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.amqp:spring-rabbit:3.1.1' + implementation 'org.hibernate:hibernate-core:6.4.4.Final' + implementation 'mysql:mysql-connector-java:8.0.33' runtimeOnly 'com.h2database:h2' - runtimeOnly 'com.mysql:mysql-connector-j:8.0.31' + runtimeOnly 'com.mysql:mysql-connector-j:8.2.0' // Validations implementation 'org.springframework.boot:spring-boot-starter-validation' 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 7159f88c..f0e2dfdb 100644 --- a/src/main/java/com/yello/server/infrastructure/batch/ChunkProcessor.java +++ b/src/main/java/com/yello/server/infrastructure/batch/ChunkProcessor.java @@ -3,6 +3,7 @@ import com.yello.server.domain.user.entity.User; import lombok.RequiredArgsConstructor; +import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing; import org.springframework.batch.item.ItemProcessor; import org.springframework.context.annotation.Configuration; 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 0cf181f2..3dc3058a 100644 --- a/src/main/java/com/yello/server/infrastructure/batch/ChunkReader.java +++ b/src/main/java/com/yello/server/infrastructure/batch/ChunkReader.java @@ -6,7 +6,9 @@ import java.util.Collections; import javax.sql.DataSource; import lombok.RequiredArgsConstructor; +import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing; import org.springframework.batch.core.configuration.annotation.StepScope; +import org.springframework.batch.item.ItemReader; import org.springframework.batch.item.data.RepositoryItemReader; import org.springframework.batch.item.data.builder.RepositoryItemReaderBuilder; import org.springframework.batch.item.database.JdbcCursorItemReader; @@ -23,8 +25,8 @@ import org.springframework.data.domain.Sort; import org.springframework.jdbc.core.BeanPropertyRowMapper; -@RequiredArgsConstructor @Configuration +@RequiredArgsConstructor public class ChunkReader { private final UserJpaRepository userRepository; @@ -54,6 +56,17 @@ public JdbcCursorItemReader jdbcCursorItemReader() { .build(); } + @Bean + @StepScope + public ItemReader userDataItemReader() { + return new JpaPagingItemReaderBuilder() + .name("exampleItemReader") + .entityManagerFactory(this.entityManagerFactory) + .pageSize(10) + .queryString("SELECT u FROM User u") + .build(); + } + @Bean @StepScope public JpaPagingItemReader userDataJpaPagingItemReader() { @@ -61,7 +74,7 @@ public JpaPagingItemReader userDataJpaPagingItemReader() { return new JpaPagingItemReaderBuilder() .name("userDataReader") .pageSize(100) - .queryString("SELECT u FROM USER u ORDER BY id") + .queryString("SELECT u FROM User u WHERE deletedAt is NULL ORDER BY id") .entityManagerFactory(entityManagerFactory) .build(); } @@ -75,7 +88,7 @@ public JdbcPagingItemReader userDataJdbcPagingItemReader() throws Exceptio .fetchSize(100) .dataSource(dataSource) .queryProvider(createUserDataQueryProvider()) - .rowMapper(new BeanPropertyRowMapper<>(User.class)) + .rowMapper(new UserRowMapper()) .name("jdbcPagingItemReader") .build(); } diff --git a/src/main/java/com/yello/server/infrastructure/batch/ChunkWriter.java b/src/main/java/com/yello/server/infrastructure/batch/ChunkWriter.java index 8b3f8ed7..17941a7c 100644 --- a/src/main/java/com/yello/server/infrastructure/batch/ChunkWriter.java +++ b/src/main/java/com/yello/server/infrastructure/batch/ChunkWriter.java @@ -3,6 +3,7 @@ import com.yello.server.domain.user.entity.User; import com.yello.server.infrastructure.firebase.service.NotificationService; import lombok.RequiredArgsConstructor; +import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing; import org.springframework.batch.core.configuration.annotation.StepScope; import org.springframework.batch.item.ItemWriter; import org.springframework.context.annotation.Bean; 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 8bfe424d..9bfd713e 100644 --- a/src/main/java/com/yello/server/infrastructure/batch/JobConfiguration.java +++ b/src/main/java/com/yello/server/infrastructure/batch/JobConfiguration.java @@ -3,6 +3,7 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.batch.core.Job; +import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing; import org.springframework.batch.core.job.builder.JobBuilder; import org.springframework.batch.core.repository.JobRepository; import org.springframework.context.annotation.Bean; @@ -10,8 +11,8 @@ import org.springframework.transaction.PlatformTransactionManager; @Slf4j -@RequiredArgsConstructor @Configuration +@RequiredArgsConstructor public class JobConfiguration { private final StepConfiguration stepConfiguration; 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 f46f6717..f4bd9d11 100644 --- a/src/main/java/com/yello/server/infrastructure/batch/StepConfiguration.java +++ b/src/main/java/com/yello/server/infrastructure/batch/StepConfiguration.java @@ -4,6 +4,8 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.batch.core.Step; +import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing; +import org.springframework.batch.core.configuration.annotation.JobScope; import org.springframework.batch.core.repository.JobRepository; import org.springframework.batch.core.step.builder.StepBuilder; import org.springframework.context.annotation.Bean; @@ -11,8 +13,8 @@ import org.springframework.transaction.PlatformTransactionManager; @Slf4j -@RequiredArgsConstructor @Configuration +@RequiredArgsConstructor public class StepConfiguration { private final ChunkReader chunkReader; @@ -20,12 +22,12 @@ public class StepConfiguration { private final ChunkWriter chunkWriter; @Bean + @JobScope public Step lunchEventAlarmStep(JobRepository jobRepository, PlatformTransactionManager transactionManager) throws Exception { return new StepBuilder("lunchEventStep", jobRepository) - .chunk(10, transactionManager) + .chunk(100, transactionManager) .reader(chunkReader.userDataJdbcPagingItemReader()) - .processor(chunkProcessor.lunchEventProcessor()) .writer(chunkWriter.lunchEventWriter()) .build(); } diff --git a/src/main/java/com/yello/server/infrastructure/batch/UserRowMapper.java b/src/main/java/com/yello/server/infrastructure/batch/UserRowMapper.java new file mode 100644 index 00000000..02d8abf0 --- /dev/null +++ b/src/main/java/com/yello/server/infrastructure/batch/UserRowMapper.java @@ -0,0 +1,18 @@ +package com.yello.server.infrastructure.batch; + +import com.yello.server.domain.user.entity.User; +import org.springframework.jdbc.core.RowMapper; + +import java.sql.ResultSet; +import java.sql.SQLException; + +public class UserRowMapper implements RowMapper { + @Override + public User mapRow(ResultSet rs, int rowNum) throws SQLException { + return User.builder() + .id(rs.getLong("id")) + .name(rs.getString("name")) + .yelloId(rs.getString("yello_id")) + .build(); + } +} diff --git a/src/main/java/com/yello/server/infrastructure/firebase/service/NotificationFcmService.java b/src/main/java/com/yello/server/infrastructure/firebase/service/NotificationFcmService.java index 0ff43101..58aa485c 100644 --- a/src/main/java/com/yello/server/infrastructure/firebase/service/NotificationFcmService.java +++ b/src/main/java/com/yello/server/infrastructure/firebase/service/NotificationFcmService.java @@ -120,7 +120,6 @@ public EmptyObject adminSendCustomNotification(Long adminId, NotificationCustomM @Override public void sendLunchEventNotification(User user) { - System.out.println(user.getId() + " asfsfsdfsd"); final User receiver = userRepository.getById(user.getId()); NotificationMessage notificationMessage = diff --git a/src/main/java/com/yello/server/infrastructure/scheduler/EventScheduler.java b/src/main/java/com/yello/server/infrastructure/scheduler/EventScheduler.java index 729cfa58..8138eeb7 100644 --- a/src/main/java/com/yello/server/infrastructure/scheduler/EventScheduler.java +++ b/src/main/java/com/yello/server/infrastructure/scheduler/EventScheduler.java @@ -34,7 +34,7 @@ public class EventScheduler { private final PlatformTransactionManager transactionManager; private final UserDataRepository userDataRepository; - @Scheduled(cron="0 19 2 * * ?") + @Scheduled(cron="0 58 10 * * ?") public void lunchEventRunJob() { //JobParamter의 역할은 반복해서 실행되는 Job의 유일한 ID임, 동일한 값이 세팅되면 두번째부터 실행안됨) From a5f02fb88ea4e21e6e4e2c85fea8f249121d1a04 Mon Sep 17 00:00:00 2001 From: hyeonjeongs Date: Thu, 29 Feb 2024 11:05:46 +0900 Subject: [PATCH 15/16] YEL-214 [feat] formatting --- .../infrastructure/batch/ChunkProcessor.java | 3 +- .../infrastructure/batch/ChunkReader.java | 60 +++++++++---------- .../infrastructure/batch/ChunkWriter.java | 1 - .../batch/JobConfiguration.java | 1 - .../batch/StepConfiguration.java | 11 ++-- .../scheduler/EventScheduler.java | 11 +--- 6 files changed, 35 insertions(+), 52 deletions(-) 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 f0e2dfdb..0aae1a7a 100644 --- a/src/main/java/com/yello/server/infrastructure/batch/ChunkProcessor.java +++ b/src/main/java/com/yello/server/infrastructure/batch/ChunkProcessor.java @@ -3,7 +3,6 @@ import com.yello.server.domain.user.entity.User; import lombok.RequiredArgsConstructor; -import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing; import org.springframework.batch.item.ItemProcessor; import org.springframework.context.annotation.Configuration; @@ -12,7 +11,7 @@ public class ChunkProcessor { public ItemProcessor lunchEventProcessor() { ItemProcessor item = user -> { - System.out.println(user.getId() + ", "+ user.getName() + " dds121212"); + System.out.println(user.getId() + ", " + user.getName() + " dds121212"); return user; }; return item; 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 3dc3058a..1351b38e 100644 --- a/src/main/java/com/yello/server/infrastructure/batch/ChunkReader.java +++ b/src/main/java/com/yello/server/infrastructure/batch/ChunkReader.java @@ -3,19 +3,12 @@ import com.yello.server.domain.user.entity.User; import com.yello.server.domain.user.repository.UserJpaRepository; import jakarta.persistence.EntityManagerFactory; -import java.util.Collections; -import javax.sql.DataSource; import lombok.RequiredArgsConstructor; -import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing; import org.springframework.batch.core.configuration.annotation.StepScope; import org.springframework.batch.item.ItemReader; import org.springframework.batch.item.data.RepositoryItemReader; import org.springframework.batch.item.data.builder.RepositoryItemReaderBuilder; -import org.springframework.batch.item.database.JdbcCursorItemReader; -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.*; import org.springframework.batch.item.database.builder.JdbcCursorItemReaderBuilder; import org.springframework.batch.item.database.builder.JdbcPagingItemReaderBuilder; import org.springframework.batch.item.database.builder.JpaPagingItemReaderBuilder; @@ -25,6 +18,9 @@ import org.springframework.data.domain.Sort; import org.springframework.jdbc.core.BeanPropertyRowMapper; +import javax.sql.DataSource; +import java.util.Collections; + @Configuration @RequiredArgsConstructor public class ChunkReader { @@ -38,22 +34,22 @@ public class ChunkReader { public RepositoryItemReader usersDataRepositoryItemReader() { return new RepositoryItemReaderBuilder() - .name("userDataReader") - .repository(userRepository) - .methodName("findAllByPageable") - .pageSize(100) - .sorts(Collections.singletonMap("id", Sort.Direction.ASC)) - .build(); + .name("userDataReader") + .repository(userRepository) + .methodName("findAllByPageable") + .pageSize(100) + .sorts(Collections.singletonMap("id", Sort.Direction.ASC)) + .build(); } public JdbcCursorItemReader jdbcCursorItemReader() { return new JdbcCursorItemReaderBuilder() - .fetchSize(10) - .dataSource(dataSource) - .rowMapper(new BeanPropertyRowMapper<>(User.class)) - .sql("SELECT u.id, u.name FROM user u WHERE u.deleted_at is NULL ORDER BY u.id") - .name("jdbcCursorItemReader") - .build(); + .fetchSize(10) + .dataSource(dataSource) + .rowMapper(new BeanPropertyRowMapper<>(User.class)) + .sql("SELECT u.id, u.name FROM user u WHERE u.deleted_at is NULL ORDER BY u.id") + .name("jdbcCursorItemReader") + .build(); } @Bean @@ -72,11 +68,11 @@ public ItemReader userDataItemReader() { public JpaPagingItemReader userDataJpaPagingItemReader() { return new JpaPagingItemReaderBuilder() - .name("userDataReader") - .pageSize(100) - .queryString("SELECT u FROM User u WHERE deletedAt is NULL ORDER BY id") - .entityManagerFactory(entityManagerFactory) - .build(); + .name("userDataReader") + .pageSize(100) + .queryString("SELECT u FROM User u WHERE deletedAt is NULL ORDER BY id") + .entityManagerFactory(entityManagerFactory) + .build(); } @Bean @@ -84,13 +80,13 @@ public JpaPagingItemReader userDataJpaPagingItemReader() { public JdbcPagingItemReader userDataJdbcPagingItemReader() throws Exception { return new JdbcPagingItemReaderBuilder() - .pageSize(100) - .fetchSize(100) - .dataSource(dataSource) - .queryProvider(createUserDataQueryProvider()) - .rowMapper(new UserRowMapper()) - .name("jdbcPagingItemReader") - .build(); + .pageSize(100) + .fetchSize(100) + .dataSource(dataSource) + .queryProvider(createUserDataQueryProvider()) + .rowMapper(new UserRowMapper()) + .name("jdbcPagingItemReader") + .build(); } @Bean diff --git a/src/main/java/com/yello/server/infrastructure/batch/ChunkWriter.java b/src/main/java/com/yello/server/infrastructure/batch/ChunkWriter.java index 17941a7c..8b3f8ed7 100644 --- a/src/main/java/com/yello/server/infrastructure/batch/ChunkWriter.java +++ b/src/main/java/com/yello/server/infrastructure/batch/ChunkWriter.java @@ -3,7 +3,6 @@ import com.yello.server.domain.user.entity.User; import com.yello.server.infrastructure.firebase.service.NotificationService; import lombok.RequiredArgsConstructor; -import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing; import org.springframework.batch.core.configuration.annotation.StepScope; import org.springframework.batch.item.ItemWriter; import org.springframework.context.annotation.Bean; 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 9bfd713e..b15623ee 100644 --- a/src/main/java/com/yello/server/infrastructure/batch/JobConfiguration.java +++ b/src/main/java/com/yello/server/infrastructure/batch/JobConfiguration.java @@ -3,7 +3,6 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.batch.core.Job; -import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing; import org.springframework.batch.core.job.builder.JobBuilder; import org.springframework.batch.core.repository.JobRepository; import org.springframework.context.annotation.Bean; 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 f4bd9d11..6a29e882 100644 --- a/src/main/java/com/yello/server/infrastructure/batch/StepConfiguration.java +++ b/src/main/java/com/yello/server/infrastructure/batch/StepConfiguration.java @@ -4,7 +4,6 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.batch.core.Step; -import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing; import org.springframework.batch.core.configuration.annotation.JobScope; import org.springframework.batch.core.repository.JobRepository; import org.springframework.batch.core.step.builder.StepBuilder; @@ -24,11 +23,11 @@ public class StepConfiguration { @Bean @JobScope public Step lunchEventAlarmStep(JobRepository jobRepository, - PlatformTransactionManager transactionManager) throws Exception { + PlatformTransactionManager transactionManager) throws Exception { return new StepBuilder("lunchEventStep", jobRepository) - .chunk(100, transactionManager) - .reader(chunkReader.userDataJdbcPagingItemReader()) - .writer(chunkWriter.lunchEventWriter()) - .build(); + .chunk(100, transactionManager) + .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 index 8138eeb7..0bc57dec 100644 --- a/src/main/java/com/yello/server/infrastructure/scheduler/EventScheduler.java +++ b/src/main/java/com/yello/server/infrastructure/scheduler/EventScheduler.java @@ -1,13 +1,8 @@ package com.yello.server.infrastructure.scheduler; -import com.yello.server.domain.user.entity.User; -import com.yello.server.domain.user.entity.UserData; -import com.yello.server.domain.user.entity.UserDataType; -import com.yello.server.domain.user.repository.UserDataRepository; 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; @@ -19,9 +14,6 @@ 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 @@ -32,9 +24,8 @@ public class EventScheduler { private final JobConfiguration jobConfiguration; private final JobRepository jobRepository; private final PlatformTransactionManager transactionManager; - private final UserDataRepository userDataRepository; - @Scheduled(cron="0 58 10 * * ?") + @Scheduled(cron = "0 0 12 * * ?") public void lunchEventRunJob() { //JobParamter의 역할은 반복해서 실행되는 Job의 유일한 ID임, 동일한 값이 세팅되면 두번째부터 실행안됨) From 82547af49825913b986dd0229e710695e8906bd2 Mon Sep 17 00:00:00 2001 From: hyeonjeongs Date: Thu, 29 Feb 2024 15:16:03 +0900 Subject: [PATCH 16/16] YEL-214 [feat] formatting --- .../java/com/yello/server/infrastructure/batch/ChunkWriter.java | 1 - .../yello/server/infrastructure/scheduler/EventScheduler.java | 1 - 2 files changed, 2 deletions(-) diff --git a/src/main/java/com/yello/server/infrastructure/batch/ChunkWriter.java b/src/main/java/com/yello/server/infrastructure/batch/ChunkWriter.java index 8b3f8ed7..3e489eb9 100644 --- a/src/main/java/com/yello/server/infrastructure/batch/ChunkWriter.java +++ b/src/main/java/com/yello/server/infrastructure/batch/ChunkWriter.java @@ -17,7 +17,6 @@ public class ChunkWriter { @Bean @StepScope public ItemWriter lunchEventWriter() { - return items -> items.forEach(notificationService::sendLunchEventNotification); } } diff --git a/src/main/java/com/yello/server/infrastructure/scheduler/EventScheduler.java b/src/main/java/com/yello/server/infrastructure/scheduler/EventScheduler.java index 0bc57dec..82f43bc8 100644 --- a/src/main/java/com/yello/server/infrastructure/scheduler/EventScheduler.java +++ b/src/main/java/com/yello/server/infrastructure/scheduler/EventScheduler.java @@ -32,7 +32,6 @@ public void lunchEventRunJob() { JobParameters jobParameters = new JobParametersBuilder() .addString("uuid", UUID.randomUUID().toString()) .toJobParameters(); - System.out.println("hye!!!!!!!!!!!!"); try { jobLauncher.run(jobConfiguration.lunchEventJob(jobRepository, transactionManager), jobParameters);