diff --git a/.github/workflows/cicd-dev.yml b/.github/workflows/cicd-dev.yml index 9fa58f5..dd84dc8 100644 --- a/.github/workflows/cicd-dev.yml +++ b/.github/workflows/cicd-dev.yml @@ -43,7 +43,7 @@ jobs: with: username: ubuntu host: ${{ secrets.EC2_DEV_HOST }} - key: ${{ secrets.EC2_KEY }} + key: ${{ secrets.EC2_DEV_KEY }} port: ${{ secrets.EC2_PORT }} source: "./scripts/deploy.sh" target: "/home/ubuntu/" @@ -53,7 +53,7 @@ jobs: with: username: ubuntu host: ${{ secrets.EC2_DEV_HOST }} - key: ${{ secrets.EC2_KEY }} + key: ${{ secrets.EC2_DEV_KEY }} port: ${{ secrets.EC2_PORT }} source: "./docker-compose.yml" target: "/home/ubuntu/" @@ -71,7 +71,7 @@ jobs: with: username: ubuntu host: ${{ secrets.EC2_DEV_HOST }} - key: ${{ secrets.EC2_KEY }} + key: ${{ secrets.EC2_DEV_KEY }} script: | sudo docker pull ${{ secrets.DOCKER_USERNAME }}/${{ secrets.DOCKER_REPOSITORY }} chmod 777 ./scripts/deploy.sh diff --git a/.github/workflows/cicd-prod.yml b/.github/workflows/cicd-prod.yml index 248326b..63e46c9 100644 --- a/.github/workflows/cicd-prod.yml +++ b/.github/workflows/cicd-prod.yml @@ -43,7 +43,7 @@ jobs: with: username: ubuntu host: ${{ secrets.EC2_PROD_HOST }} - key: ${{ secrets.EC2_KEY }} + key: ${{ secrets.EC2_PROD_KEY }} port: ${{ secrets.EC2_PORT }} source: "./scripts/deploy.sh" target: "/home/ubuntu/" @@ -53,7 +53,7 @@ jobs: with: username: ubuntu host: ${{ secrets.EC2_PROD_HOST }} - key: ${{ secrets.EC2_KEY }} + key: ${{ secrets.EC2_PROD_KEY }} port: ${{ secrets.EC2_PORT }} source: "./docker-compose.yml" target: "/home/ubuntu/" @@ -71,7 +71,7 @@ jobs: with: username: ubuntu host: ${{ secrets.EC2_PROD_HOST }} - key: ${{ secrets.EC2_KEY }} + key: ${{ secrets.EC2_PROD_KEY }} script: | sudo docker pull ${{ secrets.DOCKER_USERNAME }}/${{ secrets.DOCKER_REPOSITORY }} chmod 777 ./scripts/deploy.sh diff --git a/doorip-api/build.gradle b/doorip-api/build.gradle index 73b4460..de4da41 100644 --- a/doorip-api/build.gradle +++ b/doorip-api/build.gradle @@ -14,6 +14,8 @@ dependencies { implementation project(path: ':doorip-domain') implementation project(path: ':doorip-external') implementation project(path: ':doorip-common') + implementation project(path: ':doorip-event-publisher') + implementation project(path: ':doorip-event-subscriber') } jar { diff --git a/doorip-api/src/main/java/org/doorip/DooripApplication.java b/doorip-api/src/main/java/org/doorip/DooripApplication.java index 6a59713..d81e403 100644 --- a/doorip-api/src/main/java/org/doorip/DooripApplication.java +++ b/doorip-api/src/main/java/org/doorip/DooripApplication.java @@ -3,9 +3,7 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -@SpringBootApplication( - scanBasePackageClasses = {DomainRoot.class, CommonRoot.class, ExternalRoot.class} -) +@SpringBootApplication public class DooripApplication { public static void main(String[] args) { SpringApplication.run(DooripApplication.class, args); diff --git a/doorip-api/src/main/java/org/doorip/user/service/UserService.java b/doorip-api/src/main/java/org/doorip/user/service/UserService.java index 36e55ff..828d13e 100644 --- a/doorip-api/src/main/java/org/doorip/user/service/UserService.java +++ b/doorip-api/src/main/java/org/doorip/user/service/UserService.java @@ -4,6 +4,7 @@ import org.doorip.auth.jwt.JwtProvider; import org.doorip.auth.jwt.JwtValidator; import org.doorip.auth.jwt.Token; +import org.doorip.event.SignUpEvent; import org.doorip.exception.ConflictException; import org.doorip.exception.EntityNotFoundException; import org.doorip.exception.InvalidValueException; @@ -11,14 +12,10 @@ import org.doorip.message.ErrorMessage; import org.doorip.message.EventMessage; import org.doorip.openfeign.apple.AppleOAuthProvider; -import org.doorip.openfeign.discord.DiscordMessageProvider; import org.doorip.openfeign.kakao.KakaoOAuthProvider; +import org.doorip.publisher.EventPublisher; import org.doorip.user.domain.*; -import org.doorip.user.dto.request.ResultUpdateRequest; -import org.doorip.user.dto.request.UserReissueRequest; -import org.doorip.user.dto.request.UserSignInRequest; -import org.doorip.user.dto.request.UserSignUpRequest; -import org.doorip.user.dto.request.ProfileUpdateRequest; +import org.doorip.user.dto.request.*; import org.doorip.user.dto.response.ProfileGetResponse; import org.doorip.user.dto.response.UserSignInResponse; import org.doorip.user.dto.response.UserSignUpResponse; @@ -46,7 +43,7 @@ public class UserService { private final JwtValidator jwtValidator; private final AppleOAuthProvider appleOAuthProvider; private final KakaoOAuthProvider kakaoOAuthProvider; - private final DiscordMessageProvider discordMessageProvider; + private final EventPublisher eventPublisher; @Transactional(readOnly = true) public void splash(Long userId) { @@ -71,7 +68,8 @@ public UserSignUpResponse signUp(String token, UserSignUpRequest request) { User savedUser = saveUser(request, platformId, enumPlatform); Token issueToken = jwtProvider.issueToken(savedUser.getId()); updateRefreshToken(issueToken.refreshToken(), savedUser); - discordMessageProvider.sendMessage(EventMessage.SIGN_UP_EVENT); + int userCount = userRepository.countUser(); + eventPublisher.publishSignUpEvent(SignUpEvent.of(EventMessage.SIGN_UP_EVENT, savedUser.getName(), userCount)); return UserSignUpResponse.of(issueToken, savedUser.getId()); } diff --git a/doorip-common/src/main/java/org/doorip/CommonRoot.java b/doorip-common/src/main/java/org/doorip/CommonRoot.java deleted file mode 100644 index 86d06f6..0000000 --- a/doorip-common/src/main/java/org/doorip/CommonRoot.java +++ /dev/null @@ -1,4 +0,0 @@ -package org.doorip; - -public interface CommonRoot { -} diff --git a/doorip-common/src/main/java/org/doorip/event/SignUpEvent.java b/doorip-common/src/main/java/org/doorip/event/SignUpEvent.java new file mode 100644 index 0000000..759ff51 --- /dev/null +++ b/doorip-common/src/main/java/org/doorip/event/SignUpEvent.java @@ -0,0 +1,13 @@ +package org.doorip.event; + +import org.doorip.message.EventMessage; + +public record SignUpEvent( + EventMessage eventMessage, + String name, + int count +) { + public static SignUpEvent of(EventMessage eventMessage, String name, int count) { + return new SignUpEvent(eventMessage, name, count); + } +} diff --git a/doorip-common/src/main/java/org/doorip/message/EventMessage.java b/doorip-common/src/main/java/org/doorip/message/EventMessage.java index 7e83a66..577b3c0 100644 --- a/doorip-common/src/main/java/org/doorip/message/EventMessage.java +++ b/doorip-common/src/main/java/org/doorip/message/EventMessage.java @@ -7,7 +7,7 @@ @RequiredArgsConstructor(access = AccessLevel.PRIVATE) @Getter public enum EventMessage { - SIGN_UP_EVENT("doorip 서비스에 회원가입 이벤트가 발생했습니다. 🎉"); + SIGN_UP_EVENT("[🎉 doorip 회원가입 🎉]\n>> 닉네임: [%s]\n>> 현재 가입자 수: [%d명]"); private final String message; } diff --git a/doorip-domain/src/main/java/org/doorip/DomainRoot.java b/doorip-domain/src/main/java/org/doorip/DomainRoot.java deleted file mode 100644 index c782f51..0000000 --- a/doorip-domain/src/main/java/org/doorip/DomainRoot.java +++ /dev/null @@ -1,4 +0,0 @@ -package org.doorip; - -public interface DomainRoot { -} diff --git a/doorip-domain/src/main/java/org/doorip/user/repository/UserRepository.java b/doorip-domain/src/main/java/org/doorip/user/repository/UserRepository.java index 42be847..d58de29 100644 --- a/doorip-domain/src/main/java/org/doorip/user/repository/UserRepository.java +++ b/doorip-domain/src/main/java/org/doorip/user/repository/UserRepository.java @@ -3,6 +3,7 @@ import org.doorip.user.domain.Platform; import org.doorip.user.domain.User; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; import java.util.Optional; @@ -10,4 +11,7 @@ public interface UserRepository extends JpaRepository { Optional findUserByPlatformAndPlatformId(Platform platform, String platformId); boolean existsUserByPlatformAndPlatformId(Platform platform, String platformId); + + @Query("select count(*) from User u") + int countUser(); } diff --git a/doorip-event-publisher/build.gradle b/doorip-event-publisher/build.gradle new file mode 100644 index 0000000..f15df54 --- /dev/null +++ b/doorip-event-publisher/build.gradle @@ -0,0 +1,12 @@ +dependencies { + implementation 'org.springframework.boot:spring-boot-starter-web' + implementation project(path: ':doorip-common') +} + +bootJar { + enabled = false +} + +jar { + enabled = true +} \ No newline at end of file diff --git a/doorip-event-publisher/src/main/java/org/doorip/publisher/EventPublisher.java b/doorip-event-publisher/src/main/java/org/doorip/publisher/EventPublisher.java new file mode 100644 index 0000000..0b04840 --- /dev/null +++ b/doorip-event-publisher/src/main/java/org/doorip/publisher/EventPublisher.java @@ -0,0 +1,19 @@ +package org.doorip.publisher; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.doorip.event.SignUpEvent; +import org.springframework.context.ApplicationEventPublisher; +import org.springframework.stereotype.Component; + +@Slf4j +@RequiredArgsConstructor +@Component +public class EventPublisher { + private final ApplicationEventPublisher eventPublisher; + + public void publishSignUpEvent(SignUpEvent event) { + log.info("[publish] sign up event {}", event); + eventPublisher.publishEvent(event); + } +} diff --git a/doorip-event-subscriber/build.gradle b/doorip-event-subscriber/build.gradle new file mode 100644 index 0000000..eedd44f --- /dev/null +++ b/doorip-event-subscriber/build.gradle @@ -0,0 +1,13 @@ +dependencies { + implementation 'org.springframework.boot:spring-boot-starter-web' + implementation project(path: ':doorip-common') + implementation project(path: ':doorip-external') +} + +bootJar { + enabled = false +} + +jar { + enabled = true +} \ No newline at end of file diff --git a/doorip-event-subscriber/src/main/java/org/doorip/config/AsyncConfig.java b/doorip-event-subscriber/src/main/java/org/doorip/config/AsyncConfig.java new file mode 100644 index 0000000..7cf6f0e --- /dev/null +++ b/doorip-event-subscriber/src/main/java/org/doorip/config/AsyncConfig.java @@ -0,0 +1,23 @@ +package org.doorip.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.EnableAsync; +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; + +import java.util.concurrent.Executor; + +@EnableAsync +@Configuration +public class AsyncConfig { + @Bean + public Executor threadPoolTaskExecutor() { + ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); + executor.setCorePoolSize(3); + executor.setMaxPoolSize(30); + executor.setQueueCapacity(100); + executor.setThreadNamePrefix("async-executor-"); + executor.initialize(); + return executor; + } +} diff --git a/doorip-event-subscriber/src/main/java/org/doorip/subscriber/EventSubscriber.java b/doorip-event-subscriber/src/main/java/org/doorip/subscriber/EventSubscriber.java new file mode 100644 index 0000000..8c2681c --- /dev/null +++ b/doorip-event-subscriber/src/main/java/org/doorip/subscriber/EventSubscriber.java @@ -0,0 +1,26 @@ +package org.doorip.subscriber; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.doorip.event.SignUpEvent; +import org.doorip.message.EventMessage; +import org.doorip.openfeign.discord.DiscordMessageProvider; +import org.springframework.context.event.EventListener; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Component; + +@Slf4j +@RequiredArgsConstructor +@Component +public class EventSubscriber { + private final DiscordMessageProvider discordMessageProvider; + + @Async + @EventListener + public void subscribeSignUpEvent(SignUpEvent event) { + log.info("[subscribe] sign up event {}", event); + EventMessage eventMessage = event.eventMessage(); + String message = String.format(eventMessage.getMessage(), event.name(), event.count()); + discordMessageProvider.sendMessage(message); + } +} diff --git a/doorip-external/src/main/java/org/doorip/ExternalRoot.java b/doorip-external/src/main/java/org/doorip/ExternalRoot.java deleted file mode 100644 index bbd191c..0000000 --- a/doorip-external/src/main/java/org/doorip/ExternalRoot.java +++ /dev/null @@ -1,4 +0,0 @@ -package org.doorip; - -public interface ExternalRoot { -} diff --git a/doorip-external/src/main/java/org/doorip/config/FeignClientConfig.java b/doorip-external/src/main/java/org/doorip/config/FeignClientConfig.java index 1b41be6..5d85133 100644 --- a/doorip-external/src/main/java/org/doorip/config/FeignClientConfig.java +++ b/doorip-external/src/main/java/org/doorip/config/FeignClientConfig.java @@ -1,10 +1,9 @@ package org.doorip.config; -import org.doorip.ExternalRoot; import org.springframework.cloud.openfeign.EnableFeignClients; import org.springframework.context.annotation.Configuration; @Configuration -@EnableFeignClients(basePackageClasses = ExternalRoot.class) +@EnableFeignClients(basePackages = "org.doorip") public class FeignClientConfig { } diff --git a/doorip-external/src/main/java/org/doorip/openfeign/discord/DiscordMessageProvider.java b/doorip-external/src/main/java/org/doorip/openfeign/discord/DiscordMessageProvider.java index 6780e22..c365368 100644 --- a/doorip-external/src/main/java/org/doorip/openfeign/discord/DiscordMessageProvider.java +++ b/doorip-external/src/main/java/org/doorip/openfeign/discord/DiscordMessageProvider.java @@ -4,7 +4,6 @@ import lombok.RequiredArgsConstructor; import org.doorip.exception.InvalidValueException; import org.doorip.message.ErrorMessage; -import org.doorip.message.EventMessage; import org.springframework.stereotype.Component; import static org.doorip.openfeign.discord.DiscordMessage.createDiscordMessage; @@ -14,8 +13,8 @@ public class DiscordMessageProvider { private final DiscordFeignClient discordFeignClient; - public void sendMessage(EventMessage eventMessage) { - DiscordMessage discordMessage = createDiscordMessage(eventMessage.getMessage()); + public void sendMessage(String message) { + DiscordMessage discordMessage = createDiscordMessage(message); sendMessageToDiscord(discordMessage); } diff --git a/settings.gradle b/settings.gradle index 7417e93..8fc3086 100644 --- a/settings.gradle +++ b/settings.gradle @@ -3,3 +3,6 @@ include 'doorip-api' include 'doorip-domain' include 'doorip-common' include 'doorip-external' +include 'doorip-event-publisher' +include 'doorip-event-subscriber' +