From e3e4aa19299a8330abb7cdbb7db7962cb95a8beb Mon Sep 17 00:00:00 2001 From: songhaechan Date: Sun, 22 Sep 2024 02:37:10 +0900 Subject: [PATCH 01/22] hotfix: recover --- .gitignore | 5 ++ .../amorgakco/backend/global/BaseTime.java | 4 +- .../amorgakco/backend/global/IdResponse.java | 3 +- .../global/argumentresolver/AuthMember.java | 3 +- .../AuthMemberArgumentResolver.java | 2 - .../global/argumentresolver/AuthMemberId.java | 3 +- .../AuthMemberIdArgumentResolver.java | 1 - .../global/config/ConverterConfig.java | 2 - .../backend/global/config/CoolSmsConfig.java | 1 - .../backend/global/config/CorsConfig.java | 1 - .../global/config/CustomSpringELParser.java | 21 ++++++ .../backend/global/config/FcmInitializer.java | 4 +- .../backend/global/config/GeometryConfig.java | 14 ---- .../global/config/HandlerResolverConfig.java | 2 - .../config/KakaoRedirectionLoginUrl.java | 3 +- .../global/config/Oauth2LoginUrlConfig.java | 2 - .../backend/global/config/RabbitMQConfig.java | 3 +- .../global/config/RestClientConfig.java | 1 - .../global/config/SecretKeyConfig.java | 4 +- .../backend/global/config/SecurityConfig.java | 7 +- .../config/redisson/AopForTransaction.java | 15 +++++ .../backend/global/config/redisson/Lock.java | 20 ++++++ .../global/config/redisson/LockAop.java | 52 ++++++++++++++ .../config/redisson/RedissonConfig.java | 22 ++++++ .../backend/global/exception/ErrorCode.java | 9 ++- .../exception/GlobalExceptionResolver.java | 17 ++++- .../exception/IllegalAccessException.java | 12 ++++ .../backend/global/oauth/MemberPrincipal.java | 2 - .../backend/global/rabbitmq/ExchangeName.java | 3 +- .../global/rabbitmq/RabbitMQProperties.java | 3 +- .../backend/global/rabbitmq/RoutingKey.java | 3 +- .../global/response/SuccessResponse.java | 3 +- .../security/JwtAccessDeniedHandler.java | 1 - .../security/JwtAuthenticationEntryPoint.java | 1 - .../security/JwtAuthenticationFilter.java | 3 - .../security/JwtExceptionHandlingFilter.java | 3 - .../group/controller/GroupController.java | 11 ++- .../controller/GroupLocationController.java | 2 - .../backend/group/domain/Duration.java | 2 - .../amorgakco/backend/group/domain/Group.java | 39 ++++++++--- .../group/domain/location/Location.java | 2 - .../domain/location/LocationCalculator.java | 6 +- .../backend/group/dto/GroupBasicResponse.java | 3 +- .../group/dto/GroupDetailResponse.java | 3 +- .../backend/group/dto/GroupLocation.java | 3 +- .../backend/group/dto/GroupMember.java | 3 +- .../group/dto/GroupRegisterRequest.java | 4 +- .../backend/group/dto/GroupSearchRequest.java | 3 +- .../group/dto/GroupSearchResponse.java | 3 +- .../dto/LocationVerificationRequest.java | 3 +- .../group/repository/GroupRepository.java | 1 - .../backend/group/service/GroupService.java | 2 - .../group/service/S2GroupLocationService.java | 2 - .../group/service/mapper/GroupMapper.java | 1 - .../search/CityLevelSearchStrategy.java | 1 - .../search/DongLevelSearchStrategy.java | 1 - .../service/search/GroupSearchStrategy.java | 20 +++--- .../group/service/search/S2CellSearch.java | 16 ++--- .../GroupParticipationController.java | 11 ++- .../domain/GroupParticipation.java | 6 +- .../GroupParticipationRepository.java | 1 - .../service/GroupParticipationService.java | 61 +++++++++-------- .../mapper/GroupParticipationMapper.java | 1 - .../backend/jwt/controller/JwtController.java | 10 +-- .../jwt/controller/JwtCookieLoader.java | 1 - .../backend/jwt/domain/RefreshToken.java | 4 +- .../backend/jwt/dto/AccessTokenResponse.java | 3 +- .../backend/jwt/dto/MemberAccessToken.java | 3 +- .../backend/jwt/dto/MemberTokens.java | 3 +- .../repository/RefreshTokenRepository.java | 4 +- .../backend/jwt/service/JwtCreator.java | 5 +- .../backend/jwt/service/JwtProperties.java | 3 +- .../backend/jwt/service/JwtService.java | 5 +- .../backend/jwt/service/JwtValidator.java | 8 +-- .../member/controller/MemberController.java | 2 - .../backend/member/domain/Member.java | 41 ++++++++++-- .../backend/member/domain/Roles.java | 8 ++- .../member/dto/AdditionalInfoRequest.java | 3 +- .../member/dto/PrivateMemberResponse.java | 3 +- .../member/repository/MemberRepository.java | 1 - .../backend/member/service/MemberService.java | 2 - .../member/service/mapper/MemberMapper.java | 1 - .../controller/NotificationController.java | 2 - .../notification/domain/Notification.java | 27 ++++---- .../domain/NotificationTitle.java | 14 ---- .../notification/domain/NotificationType.java | 16 +++++ .../notification/domain/SendingType.java | 7 ++ .../notification/dto/NotificationMessage.java | 3 +- .../dto/NotificationMessageResponse.java | 3 +- .../NotificationPublisherFacade.java | 32 +++++++++ .../consumer/NotificationRequest.java | 6 +- .../consumer/fcm/FcmWebPushConsumer.java | 11 ++- .../consumer/slack/SlackRequest.java | 3 +- .../consumer/slack/SlackSender.java | 1 - .../consumer/sms/CoolSmsConsumer.java | 17 +++-- .../FcmPublisher.java} | 34 ++-------- .../infrastructure/publisher/Publisher.java | 7 ++ .../publisher/SmsAndFcmPublisher.java | 19 ++++++ .../publisher/SmsPublisher.java | 26 +++++++ .../repository/NotificationRepository.java | 3 +- .../service/NotificationCreator.java | 65 +++++++++++------- .../service/NotificationService.java | 2 - .../service/mapper/NotificationMapper.java | 7 +- .../oauth2/controller/Oauth2Controller.java | 3 - .../converter/Oauth2ProviderConverter.java | 1 - .../oauth2/dto/Oauth2LoginResponse.java | 3 +- .../oauth2/dto/Oauth2MemberResponse.java | 3 +- .../backend/oauth2/provider/Oauth2Member.java | 4 +- .../provider/Oauth2ProviderSelector.java | 1 - .../provider/kakao/KakaoAuthorization.java | 3 +- .../provider/kakao/KakaoMemberResponse.java | 6 +- .../kakao/KakaoOAuth2ProviderService.java | 2 - .../provider/kakao/KakaoOauth2Properties.java | 3 +- .../backend/oauth2/service/Oauth2Service.java | 2 - .../controller/ParticipantController.java | 38 ++++++++++- .../participant/domain/Participant.java | 49 ++++++++++---- .../participant/dto/ParticipationHistory.java | 3 +- .../dto/ParticipationHistoryResponse.java | 3 +- .../participant/dto/TardinessRequest.java | 7 ++ .../repository/ParticipantRepository.java | 4 +- .../service/ParticipantService.java | 61 +++++++++++++++-- .../service/mapper/ParticipantMapper.java | 1 - .../fixture/group/TestGroupFactory.java | 5 +- .../notification/TestNotificationFactory.java | 4 +- .../backend/group/domain/GroupTest.java | 9 +-- .../GroupParticipationControllerTest.java | 23 +++---- .../domain/GroupParticipationTest.java | 5 +- .../service/ParticipantServiceTest.java | 67 +++++++++++++++++++ src/test/resources/application-test.yml | 29 ++++++++ 129 files changed, 851 insertions(+), 369 deletions(-) create mode 100644 src/main/java/com/amorgakco/backend/global/config/CustomSpringELParser.java delete mode 100644 src/main/java/com/amorgakco/backend/global/config/GeometryConfig.java create mode 100644 src/main/java/com/amorgakco/backend/global/config/redisson/AopForTransaction.java create mode 100644 src/main/java/com/amorgakco/backend/global/config/redisson/Lock.java create mode 100644 src/main/java/com/amorgakco/backend/global/config/redisson/LockAop.java create mode 100644 src/main/java/com/amorgakco/backend/global/config/redisson/RedissonConfig.java delete mode 100644 src/main/java/com/amorgakco/backend/notification/domain/NotificationTitle.java create mode 100644 src/main/java/com/amorgakco/backend/notification/domain/NotificationType.java create mode 100644 src/main/java/com/amorgakco/backend/notification/domain/SendingType.java create mode 100644 src/main/java/com/amorgakco/backend/notification/infrastructure/NotificationPublisherFacade.java rename src/main/java/com/amorgakco/backend/notification/infrastructure/{NotificationPublisher.java => publisher/FcmPublisher.java} (50%) create mode 100644 src/main/java/com/amorgakco/backend/notification/infrastructure/publisher/Publisher.java create mode 100644 src/main/java/com/amorgakco/backend/notification/infrastructure/publisher/SmsAndFcmPublisher.java create mode 100644 src/main/java/com/amorgakco/backend/notification/infrastructure/publisher/SmsPublisher.java create mode 100644 src/main/java/com/amorgakco/backend/participant/dto/TardinessRequest.java create mode 100644 src/test/java/com/amorgakco/backend/participant/service/ParticipantServiceTest.java create mode 100644 src/test/resources/application-test.yml diff --git a/.gitignore b/.gitignore index d58d89d..5b7e909 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,11 @@ src/main/resources/application-oauth2local.yml src/main/resources/application-jwt.yml src/main/resources/application-notification.yml src/main/resources/fcm-secret.json +src/test/resources/fcm-secret.json +src/test/resources/application-jwt.yml +src/test/resources/application-oauth2.yml +src/test/resources/application-notification.yml + docker/ .docker-conf/ diff --git a/src/main/java/com/amorgakco/backend/global/BaseTime.java b/src/main/java/com/amorgakco/backend/global/BaseTime.java index 40b5924..53ad8de 100644 --- a/src/main/java/com/amorgakco/backend/global/BaseTime.java +++ b/src/main/java/com/amorgakco/backend/global/BaseTime.java @@ -3,7 +3,6 @@ import jakarta.persistence.Column; import jakarta.persistence.EntityListeners; import jakarta.persistence.MappedSuperclass; - import org.springframework.data.annotation.CreatedDate; import org.springframework.data.annotation.LastModifiedDate; import org.springframework.data.jpa.domain.support.AuditingEntityListener; @@ -18,5 +17,6 @@ public abstract class BaseTime { @Column(updatable = false) private LocalDateTime createdAt; - @LastModifiedDate private LocalDateTime modifiedAt; + @LastModifiedDate + private LocalDateTime modifiedAt; } diff --git a/src/main/java/com/amorgakco/backend/global/IdResponse.java b/src/main/java/com/amorgakco/backend/global/IdResponse.java index 0620508..b678a7e 100644 --- a/src/main/java/com/amorgakco/backend/global/IdResponse.java +++ b/src/main/java/com/amorgakco/backend/global/IdResponse.java @@ -1,3 +1,4 @@ package com.amorgakco.backend.global; -public record IdResponse(Long id) {} +public record IdResponse(Long id) { +} diff --git a/src/main/java/com/amorgakco/backend/global/argumentresolver/AuthMember.java b/src/main/java/com/amorgakco/backend/global/argumentresolver/AuthMember.java index 020b032..963952f 100644 --- a/src/main/java/com/amorgakco/backend/global/argumentresolver/AuthMember.java +++ b/src/main/java/com/amorgakco/backend/global/argumentresolver/AuthMember.java @@ -7,4 +7,5 @@ @Target(ElementType.PARAMETER) @Retention(RetentionPolicy.RUNTIME) -public @interface AuthMember {} +public @interface AuthMember { +} diff --git a/src/main/java/com/amorgakco/backend/global/argumentresolver/AuthMemberArgumentResolver.java b/src/main/java/com/amorgakco/backend/global/argumentresolver/AuthMemberArgumentResolver.java index e75d026..e753b10 100644 --- a/src/main/java/com/amorgakco/backend/global/argumentresolver/AuthMemberArgumentResolver.java +++ b/src/main/java/com/amorgakco/backend/global/argumentresolver/AuthMemberArgumentResolver.java @@ -3,9 +3,7 @@ import com.amorgakco.backend.global.oauth.MemberPrincipal; import com.amorgakco.backend.member.domain.Member; import com.amorgakco.backend.member.service.MemberService; - import lombok.RequiredArgsConstructor; - import org.springframework.core.MethodParameter; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Component; diff --git a/src/main/java/com/amorgakco/backend/global/argumentresolver/AuthMemberId.java b/src/main/java/com/amorgakco/backend/global/argumentresolver/AuthMemberId.java index 42fadad..858c38d 100644 --- a/src/main/java/com/amorgakco/backend/global/argumentresolver/AuthMemberId.java +++ b/src/main/java/com/amorgakco/backend/global/argumentresolver/AuthMemberId.java @@ -7,4 +7,5 @@ @Target(ElementType.PARAMETER) @Retention(RetentionPolicy.RUNTIME) -public @interface AuthMemberId {} +public @interface AuthMemberId { +} diff --git a/src/main/java/com/amorgakco/backend/global/argumentresolver/AuthMemberIdArgumentResolver.java b/src/main/java/com/amorgakco/backend/global/argumentresolver/AuthMemberIdArgumentResolver.java index 5e690a0..3c79080 100644 --- a/src/main/java/com/amorgakco/backend/global/argumentresolver/AuthMemberIdArgumentResolver.java +++ b/src/main/java/com/amorgakco/backend/global/argumentresolver/AuthMemberIdArgumentResolver.java @@ -1,7 +1,6 @@ package com.amorgakco.backend.global.argumentresolver; import com.amorgakco.backend.global.oauth.MemberPrincipal; - import org.springframework.core.MethodParameter; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Component; diff --git a/src/main/java/com/amorgakco/backend/global/config/ConverterConfig.java b/src/main/java/com/amorgakco/backend/global/config/ConverterConfig.java index 6de2f6f..4db3029 100644 --- a/src/main/java/com/amorgakco/backend/global/config/ConverterConfig.java +++ b/src/main/java/com/amorgakco/backend/global/config/ConverterConfig.java @@ -1,9 +1,7 @@ package com.amorgakco.backend.global.config; import com.amorgakco.backend.oauth2.converter.Oauth2ProviderConverter; - import lombok.RequiredArgsConstructor; - import org.springframework.context.annotation.Configuration; import org.springframework.format.FormatterRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; diff --git a/src/main/java/com/amorgakco/backend/global/config/CoolSmsConfig.java b/src/main/java/com/amorgakco/backend/global/config/CoolSmsConfig.java index 08deb95..444b993 100644 --- a/src/main/java/com/amorgakco/backend/global/config/CoolSmsConfig.java +++ b/src/main/java/com/amorgakco/backend/global/config/CoolSmsConfig.java @@ -2,7 +2,6 @@ import net.nurigo.sdk.NurigoApp; import net.nurigo.sdk.message.service.DefaultMessageService; - import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; diff --git a/src/main/java/com/amorgakco/backend/global/config/CorsConfig.java b/src/main/java/com/amorgakco/backend/global/config/CorsConfig.java index 0eaff80..fbeff70 100644 --- a/src/main/java/com/amorgakco/backend/global/config/CorsConfig.java +++ b/src/main/java/com/amorgakco/backend/global/config/CorsConfig.java @@ -1,7 +1,6 @@ package com.amorgakco.backend.global.config; import com.google.common.net.HttpHeaders; - import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; diff --git a/src/main/java/com/amorgakco/backend/global/config/CustomSpringELParser.java b/src/main/java/com/amorgakco/backend/global/config/CustomSpringELParser.java new file mode 100644 index 0000000..20757fb --- /dev/null +++ b/src/main/java/com/amorgakco/backend/global/config/CustomSpringELParser.java @@ -0,0 +1,21 @@ +package com.amorgakco.backend.global.config; + +import org.springframework.expression.ExpressionParser; +import org.springframework.expression.spel.standard.SpelExpressionParser; +import org.springframework.expression.spel.support.StandardEvaluationContext; + +public class CustomSpringELParser { + public static Object getDynamicValue(String[] parameterNames, Object[] args, String key) { + ExpressionParser parser = new SpelExpressionParser(); + StandardEvaluationContext context = new StandardEvaluationContext(); + + for (int i = 0; i < parameterNames.length; i++) { + context.setVariable(parameterNames[i], args[i]); + } + + return parser.parseExpression(key).getValue(context, Object.class); + } + + private CustomSpringELParser() { + } +} \ No newline at end of file diff --git a/src/main/java/com/amorgakco/backend/global/config/FcmInitializer.java b/src/main/java/com/amorgakco/backend/global/config/FcmInitializer.java index 532688a..13fc3df 100644 --- a/src/main/java/com/amorgakco/backend/global/config/FcmInitializer.java +++ b/src/main/java/com/amorgakco/backend/global/config/FcmInitializer.java @@ -3,14 +3,12 @@ import com.google.auth.oauth2.GoogleCredentials; import com.google.firebase.FirebaseApp; import com.google.firebase.FirebaseOptions; - import org.springframework.beans.factory.annotation.Value; import org.springframework.core.io.ClassPathResource; import org.springframework.stereotype.Component; -import java.io.IOException; - import javax.annotation.PostConstruct; +import java.io.IOException; @Component public class FcmInitializer { diff --git a/src/main/java/com/amorgakco/backend/global/config/GeometryConfig.java b/src/main/java/com/amorgakco/backend/global/config/GeometryConfig.java deleted file mode 100644 index de0dc62..0000000 --- a/src/main/java/com/amorgakco/backend/global/config/GeometryConfig.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.amorgakco.backend.global.config; - -import org.locationtech.jts.geom.GeometryFactory; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -@Configuration -public class GeometryConfig { - - @Bean - public GeometryFactory geometryFactory() { - return new GeometryFactory(); - } -} diff --git a/src/main/java/com/amorgakco/backend/global/config/HandlerResolverConfig.java b/src/main/java/com/amorgakco/backend/global/config/HandlerResolverConfig.java index a08e6e8..961ff67 100644 --- a/src/main/java/com/amorgakco/backend/global/config/HandlerResolverConfig.java +++ b/src/main/java/com/amorgakco/backend/global/config/HandlerResolverConfig.java @@ -2,9 +2,7 @@ import com.amorgakco.backend.global.argumentresolver.AuthMemberArgumentResolver; import com.amorgakco.backend.global.argumentresolver.AuthMemberIdArgumentResolver; - import lombok.RequiredArgsConstructor; - import org.springframework.context.annotation.Configuration; import org.springframework.web.method.support.HandlerMethodArgumentResolver; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; diff --git a/src/main/java/com/amorgakco/backend/global/config/KakaoRedirectionLoginUrl.java b/src/main/java/com/amorgakco/backend/global/config/KakaoRedirectionLoginUrl.java index 3f9f15f..774ddfa 100644 --- a/src/main/java/com/amorgakco/backend/global/config/KakaoRedirectionLoginUrl.java +++ b/src/main/java/com/amorgakco/backend/global/config/KakaoRedirectionLoginUrl.java @@ -1,3 +1,4 @@ package com.amorgakco.backend.global.config; -public record KakaoRedirectionLoginUrl(String redirectionUrl) {} +public record KakaoRedirectionLoginUrl(String redirectionUrl) { +} diff --git a/src/main/java/com/amorgakco/backend/global/config/Oauth2LoginUrlConfig.java b/src/main/java/com/amorgakco/backend/global/config/Oauth2LoginUrlConfig.java index 399cc0a..8e02c04 100644 --- a/src/main/java/com/amorgakco/backend/global/config/Oauth2LoginUrlConfig.java +++ b/src/main/java/com/amorgakco/backend/global/config/Oauth2LoginUrlConfig.java @@ -1,9 +1,7 @@ package com.amorgakco.backend.global.config; import com.amorgakco.backend.oauth2.provider.kakao.KakaoOauth2Properties; - import lombok.RequiredArgsConstructor; - import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.util.UriComponentsBuilder; diff --git a/src/main/java/com/amorgakco/backend/global/config/RabbitMQConfig.java b/src/main/java/com/amorgakco/backend/global/config/RabbitMQConfig.java index ed0eb40..cb442e4 100644 --- a/src/main/java/com/amorgakco/backend/global/config/RabbitMQConfig.java +++ b/src/main/java/com/amorgakco/backend/global/config/RabbitMQConfig.java @@ -4,9 +4,7 @@ import com.amorgakco.backend.global.rabbitmq.QueueName; import com.amorgakco.backend.global.rabbitmq.RabbitMQProperties; import com.amorgakco.backend.global.rabbitmq.RoutingKey; - import lombok.RequiredArgsConstructor; - import org.springframework.amqp.core.Binding; import org.springframework.amqp.core.BindingBuilder; import org.springframework.amqp.core.DirectExchange; @@ -24,6 +22,7 @@ @EnableRabbit @Configuration @RequiredArgsConstructor +//@Profile("!test") public class RabbitMQConfig { private final RabbitMQProperties properties; diff --git a/src/main/java/com/amorgakco/backend/global/config/RestClientConfig.java b/src/main/java/com/amorgakco/backend/global/config/RestClientConfig.java index 63241c7..3c532d6 100644 --- a/src/main/java/com/amorgakco/backend/global/config/RestClientConfig.java +++ b/src/main/java/com/amorgakco/backend/global/config/RestClientConfig.java @@ -1,7 +1,6 @@ package com.amorgakco.backend.global.config; import com.amorgakco.backend.oauth2.provider.kakao.KakaoRestClient; - import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.client.RestClient; diff --git a/src/main/java/com/amorgakco/backend/global/config/SecretKeyConfig.java b/src/main/java/com/amorgakco/backend/global/config/SecretKeyConfig.java index edcae8e..660f5f2 100644 --- a/src/main/java/com/amorgakco/backend/global/config/SecretKeyConfig.java +++ b/src/main/java/com/amorgakco/backend/global/config/SecretKeyConfig.java @@ -1,14 +1,12 @@ package com.amorgakco.backend.global.config; import io.jsonwebtoken.security.Keys; - import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import java.nio.charset.StandardCharsets; - import javax.crypto.SecretKey; +import java.nio.charset.StandardCharsets; @Configuration public class SecretKeyConfig { diff --git a/src/main/java/com/amorgakco/backend/global/config/SecurityConfig.java b/src/main/java/com/amorgakco/backend/global/config/SecurityConfig.java index 55e9453..2dc80a0 100644 --- a/src/main/java/com/amorgakco/backend/global/config/SecurityConfig.java +++ b/src/main/java/com/amorgakco/backend/global/config/SecurityConfig.java @@ -4,9 +4,7 @@ import com.amorgakco.backend.global.security.JwtAuthenticationEntryPoint; import com.amorgakco.backend.global.security.JwtAuthenticationFilter; import com.amorgakco.backend.global.security.JwtExceptionHandlingFilter; - import lombok.RequiredArgsConstructor; - import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; @@ -15,8 +13,8 @@ import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; -@Configuration @RequiredArgsConstructor +@Configuration public class SecurityConfig { private final JwtAuthenticationFilter jwtAuthenticationFilter; @@ -41,7 +39,8 @@ public SecurityFilterChain securityFilterChain(final HttpSecurity http) throws E "/groups/basic/**", "/groups/locations", "/members/login", - "/favicon.ico") + "/favicon.ico", + "/error") .permitAll() .anyRequest() .authenticated()) diff --git a/src/main/java/com/amorgakco/backend/global/config/redisson/AopForTransaction.java b/src/main/java/com/amorgakco/backend/global/config/redisson/AopForTransaction.java new file mode 100644 index 0000000..02eb451 --- /dev/null +++ b/src/main/java/com/amorgakco/backend/global/config/redisson/AopForTransaction.java @@ -0,0 +1,15 @@ +package com.amorgakco.backend.global.config.redisson; + +import org.aspectj.lang.ProceedingJoinPoint; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Propagation; +import org.springframework.transaction.annotation.Transactional; + +@Component +public class AopForTransaction { + + @Transactional(propagation = Propagation.REQUIRES_NEW) + public Object proceed(final ProceedingJoinPoint joinPoint) throws Throwable { + return joinPoint.proceed(); + } +} \ No newline at end of file diff --git a/src/main/java/com/amorgakco/backend/global/config/redisson/Lock.java b/src/main/java/com/amorgakco/backend/global/config/redisson/Lock.java new file mode 100644 index 0000000..526e388 --- /dev/null +++ b/src/main/java/com/amorgakco/backend/global/config/redisson/Lock.java @@ -0,0 +1,20 @@ +package com.amorgakco.backend.global.config.redisson; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.util.concurrent.TimeUnit; + +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +public @interface Lock { + + String key(); + + TimeUnit timeUnit() default TimeUnit.SECONDS; + + long waitTime() default 5L; + + long leaseTime() default 3L; +} \ No newline at end of file diff --git a/src/main/java/com/amorgakco/backend/global/config/redisson/LockAop.java b/src/main/java/com/amorgakco/backend/global/config/redisson/LockAop.java new file mode 100644 index 0000000..781e762 --- /dev/null +++ b/src/main/java/com/amorgakco/backend/global/config/redisson/LockAop.java @@ -0,0 +1,52 @@ +package com.amorgakco.backend.global.config.redisson; + +import com.amorgakco.backend.global.config.CustomSpringELParser; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.reflect.MethodSignature; +import org.redisson.api.RLock; +import org.redisson.api.RedissonClient; +import org.springframework.stereotype.Component; + +import java.lang.reflect.Method; + +@Aspect +@Component +@RequiredArgsConstructor +@Slf4j +public class LockAop { + private static final String REDISSON_LOCK_PREFIX = "LOCK:"; + + private final RedissonClient redissonClient; + private final AopForTransaction aopForTransaction; + + @Around("@annotation(com.amorgakco.backend.global.config.redisson.Lock)") + public Object lock(final ProceedingJoinPoint joinPoint) throws Throwable { + MethodSignature signature = (MethodSignature) joinPoint.getSignature(); + Method method = signature.getMethod(); + Lock lock = method.getAnnotation(Lock.class); + + String key = REDISSON_LOCK_PREFIX + CustomSpringELParser.getDynamicValue(signature.getParameterNames(), joinPoint.getArgs(), lock.key()); + RLock rLock = redissonClient.getLock(key); + + try { + boolean available = rLock.tryLock(lock.waitTime(), lock.leaseTime(), lock.timeUnit()); // (2) + if (!available) { + return false; + } + + return aopForTransaction.proceed(joinPoint); + } catch (InterruptedException e) { + throw new InterruptedException(); + } finally { + try { + rLock.unlock(); + } catch (IllegalMonitorStateException e) { + log.error("Already Unlock"); + } + } + } +} diff --git a/src/main/java/com/amorgakco/backend/global/config/redisson/RedissonConfig.java b/src/main/java/com/amorgakco/backend/global/config/redisson/RedissonConfig.java new file mode 100644 index 0000000..21ab98b --- /dev/null +++ b/src/main/java/com/amorgakco/backend/global/config/redisson/RedissonConfig.java @@ -0,0 +1,22 @@ +package com.amorgakco.backend.global.config.redisson; + +import org.redisson.Redisson; +import org.redisson.api.RedissonClient; +import org.redisson.config.Config; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; + +public class RedissonConfig { + private static final String REDISSON_HOST_PREFIX = "redis://"; + @Value("${spring.redis.host}") + private String redisHost; + @Value("${spring.redis.port}") + private int redisPort; + + @Bean + public RedissonClient redissonClient() { + Config config = new Config(); + config.useSingleServer().setAddress(REDISSON_HOST_PREFIX + redisHost + ":" + redisPort); + return Redisson.create(config); + } +} diff --git a/src/main/java/com/amorgakco/backend/global/exception/ErrorCode.java b/src/main/java/com/amorgakco/backend/global/exception/ErrorCode.java index 456bb26..08026c0 100644 --- a/src/main/java/com/amorgakco/backend/global/exception/ErrorCode.java +++ b/src/main/java/com/amorgakco/backend/global/exception/ErrorCode.java @@ -6,6 +6,9 @@ @RequiredArgsConstructor @Getter public enum ErrorCode { + // Global Error Code + NOT_VALID_ARGUMENT("001", "잘못된 입력입니다. 입력 파라미터를 다시 확인해주세요."), + // Auth Error Code ACCESS_TOKEN_EXPIRED("100", "액세스 토큰이 만료됐습니다."), REFRESH_TOKEN_REQUIRED("101", "리프레쉬 토큰을 쿠키에서 찾을 수 없습니다."), @@ -20,6 +23,9 @@ public enum ErrorCode { MEMBER_NOT_FOUND("201", "존재하지 않는 회원입니다."), DASH_NOT_ALLOWED("202", "전화번호에 '-'를 포함할 수 없습니다."), INVALID_GITHUB_URL("203", "부적절한 github 주소입니다."), + CAN_NOT_EXCEED_POSITIVE_100("204", "모각코 온도는 100도를 넘을 수 없습니다."), + CAN_NOT_UNDER_NEGATIVE_100("204", "모각코 온도는 -100도 보다 낮을 수 없습니다."), + // Group Error Code GROUP_NOT_FOUND("301", "존재하지 않는 그룹입니다."), @@ -34,7 +40,8 @@ public enum ErrorCode { PARTICIPANT_DUPLICATED("310", "중복된 회원입니다."), EXCEED_GROUP_CAPACITY("311", "그룹 수용 인원을 초과합니다."), PARTICIPATION_NOT_FOUND("312", "참여 요청을 조회할 수 없습니다."), - INVALID_DIAGONAL_DISTANCE("313", "잘못된 그룹 검색 요청입니다. 위도 경도를 확인해주세요."); + INVALID_DIAGONAL_DISTANCE("313", "잘못된 그룹 검색 요청입니다. 위도 경도를 확인해주세요."), + NOT_SAME_GROUP_PARTICIPANT("314", "동일한 그룹 내의 참여자끼리 온도를 변경할 수 있습니다."); private final String code; private final String message; diff --git a/src/main/java/com/amorgakco/backend/global/exception/GlobalExceptionResolver.java b/src/main/java/com/amorgakco/backend/global/exception/GlobalExceptionResolver.java index 2d0847f..6fc287d 100644 --- a/src/main/java/com/amorgakco/backend/global/exception/GlobalExceptionResolver.java +++ b/src/main/java/com/amorgakco/backend/global/exception/GlobalExceptionResolver.java @@ -1,16 +1,18 @@ package com.amorgakco.backend.global.exception; import com.amorgakco.backend.global.response.ErrorResponse; - import lombok.extern.slf4j.Slf4j; - import org.springframework.http.HttpStatus; import org.springframework.security.access.AccessDeniedException; import org.springframework.security.core.AuthenticationException; +import org.springframework.validation.FieldError; +import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestControllerAdvice; +import java.util.Objects; + @RestControllerAdvice @Slf4j public class GlobalExceptionResolver { @@ -26,6 +28,17 @@ private void setExceptionLog(final String message) { log.error("Error Message : {}", message); } + @ExceptionHandler(MethodArgumentNotValidException.class) + @ResponseStatus(HttpStatus.BAD_REQUEST) + public ErrorResponse checkParameter(final MethodArgumentNotValidException e) { + setExceptionLog(e.getMessage()); + FieldError fieldError = e.getBindingResult().getFieldError(); + if (Objects.isNull(fieldError)) { + return new ErrorResponse("잘못된 입력입니다."); + } + return new ErrorResponse(fieldError.getDefaultMessage()); + } + @ExceptionHandler(AccessDeniedException.class) @ResponseStatus(HttpStatus.FORBIDDEN) public ErrorResponse accessDenied(final AccessDeniedException e) { diff --git a/src/main/java/com/amorgakco/backend/global/exception/IllegalAccessException.java b/src/main/java/com/amorgakco/backend/global/exception/IllegalAccessException.java index 4cd9faa..513ddf0 100644 --- a/src/main/java/com/amorgakco/backend/global/exception/IllegalAccessException.java +++ b/src/main/java/com/amorgakco/backend/global/exception/IllegalAccessException.java @@ -36,4 +36,16 @@ public static IllegalAccessException exceedGroupCapacity() { public static IllegalAccessException invalidDiagonalDistance() { return new IllegalAccessException(ErrorCode.INVALID_DIAGONAL_DISTANCE); } + + public static IllegalAccessException notSameGroupParticipant() { + return new IllegalAccessException(ErrorCode.NOT_SAME_GROUP_PARTICIPANT); + } + + public static IllegalAccessException canNotExceedPositive100() { + return new IllegalAccessException(ErrorCode.CAN_NOT_EXCEED_POSITIVE_100); + } + + public static IllegalAccessException canNotUnderNegative100() { + return new IllegalAccessException(ErrorCode.CAN_NOT_UNDER_NEGATIVE_100); + } } diff --git a/src/main/java/com/amorgakco/backend/global/oauth/MemberPrincipal.java b/src/main/java/com/amorgakco/backend/global/oauth/MemberPrincipal.java index 9569115..6cb8638 100644 --- a/src/main/java/com/amorgakco/backend/global/oauth/MemberPrincipal.java +++ b/src/main/java/com/amorgakco/backend/global/oauth/MemberPrincipal.java @@ -1,9 +1,7 @@ package com.amorgakco.backend.global.oauth; import com.amorgakco.backend.member.domain.Roles; - import lombok.Getter; - import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.AuthorityUtils; import org.springframework.security.core.userdetails.UserDetails; diff --git a/src/main/java/com/amorgakco/backend/global/rabbitmq/ExchangeName.java b/src/main/java/com/amorgakco/backend/global/rabbitmq/ExchangeName.java index 15eaa42..1aacfb8 100644 --- a/src/main/java/com/amorgakco/backend/global/rabbitmq/ExchangeName.java +++ b/src/main/java/com/amorgakco/backend/global/rabbitmq/ExchangeName.java @@ -6,7 +6,8 @@ @RequiredArgsConstructor @Getter public enum ExchangeName { - NOTIFICATION("notification"); + NOTIFICATION("notification"), + NOTIFICATION_DEAD_LETTER("notification-dl"); private final String name; } diff --git a/src/main/java/com/amorgakco/backend/global/rabbitmq/RabbitMQProperties.java b/src/main/java/com/amorgakco/backend/global/rabbitmq/RabbitMQProperties.java index 7c14079..7215e20 100644 --- a/src/main/java/com/amorgakco/backend/global/rabbitmq/RabbitMQProperties.java +++ b/src/main/java/com/amorgakco/backend/global/rabbitmq/RabbitMQProperties.java @@ -3,4 +3,5 @@ import org.springframework.boot.context.properties.ConfigurationProperties; @ConfigurationProperties(prefix = "spring.rabbitmq") -public record RabbitMQProperties(String host, Integer port, String username, String password) {} +public record RabbitMQProperties(String host, Integer port, String username, String password) { +} diff --git a/src/main/java/com/amorgakco/backend/global/rabbitmq/RoutingKey.java b/src/main/java/com/amorgakco/backend/global/rabbitmq/RoutingKey.java index f4d3ac2..2a5ab9b 100644 --- a/src/main/java/com/amorgakco/backend/global/rabbitmq/RoutingKey.java +++ b/src/main/java/com/amorgakco/backend/global/rabbitmq/RoutingKey.java @@ -8,7 +8,8 @@ public enum RoutingKey { DELIMITER("."), NOTIFICATION_SMS(ExchangeName.NOTIFICATION.getName() + DELIMITER.key + QueueName.SMS.getName()), - NOTIFICATION_FCM(ExchangeName.NOTIFICATION.getName() + DELIMITER.key + QueueName.FCM.getName()); + NOTIFICATION_FCM(ExchangeName.NOTIFICATION.getName() + DELIMITER.key + QueueName.FCM.getName()), + NOTIFICATION_DEAD_LETTER(ExchangeName.NOTIFICATION_DEAD_LETTER.getName()); private final String key; } diff --git a/src/main/java/com/amorgakco/backend/global/response/SuccessResponse.java b/src/main/java/com/amorgakco/backend/global/response/SuccessResponse.java index 1e6f5d9..68b4c10 100644 --- a/src/main/java/com/amorgakco/backend/global/response/SuccessResponse.java +++ b/src/main/java/com/amorgakco/backend/global/response/SuccessResponse.java @@ -3,4 +3,5 @@ import lombok.Builder; @Builder -public record SuccessResponse(String status, String path, T data) {} +public record SuccessResponse(String status, String path, T data) { +} diff --git a/src/main/java/com/amorgakco/backend/global/security/JwtAccessDeniedHandler.java b/src/main/java/com/amorgakco/backend/global/security/JwtAccessDeniedHandler.java index 785bb31..2bc5785 100644 --- a/src/main/java/com/amorgakco/backend/global/security/JwtAccessDeniedHandler.java +++ b/src/main/java/com/amorgakco/backend/global/security/JwtAccessDeniedHandler.java @@ -2,7 +2,6 @@ import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; - import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.security.access.AccessDeniedException; import org.springframework.security.web.access.AccessDeniedHandler; diff --git a/src/main/java/com/amorgakco/backend/global/security/JwtAuthenticationEntryPoint.java b/src/main/java/com/amorgakco/backend/global/security/JwtAuthenticationEntryPoint.java index c98748e..bbd0287 100644 --- a/src/main/java/com/amorgakco/backend/global/security/JwtAuthenticationEntryPoint.java +++ b/src/main/java/com/amorgakco/backend/global/security/JwtAuthenticationEntryPoint.java @@ -2,7 +2,6 @@ import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; - import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.security.core.AuthenticationException; import org.springframework.security.web.AuthenticationEntryPoint; diff --git a/src/main/java/com/amorgakco/backend/global/security/JwtAuthenticationFilter.java b/src/main/java/com/amorgakco/backend/global/security/JwtAuthenticationFilter.java index f2c3289..b3dc0a3 100644 --- a/src/main/java/com/amorgakco/backend/global/security/JwtAuthenticationFilter.java +++ b/src/main/java/com/amorgakco/backend/global/security/JwtAuthenticationFilter.java @@ -2,14 +2,11 @@ import com.amorgakco.backend.jwt.service.JwtExtractor; import com.amorgakco.backend.jwt.service.JwtValidator; - import jakarta.servlet.FilterChain; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; - import lombok.RequiredArgsConstructor; - import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Component; diff --git a/src/main/java/com/amorgakco/backend/global/security/JwtExceptionHandlingFilter.java b/src/main/java/com/amorgakco/backend/global/security/JwtExceptionHandlingFilter.java index 02ec97b..66959b2 100644 --- a/src/main/java/com/amorgakco/backend/global/security/JwtExceptionHandlingFilter.java +++ b/src/main/java/com/amorgakco/backend/global/security/JwtExceptionHandlingFilter.java @@ -3,14 +3,11 @@ import com.amorgakco.backend.global.exception.JwtAuthenticationException; import com.amorgakco.backend.global.response.ErrorResponse; import com.fasterxml.jackson.databind.ObjectMapper; - import jakarta.servlet.FilterChain; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; - import lombok.RequiredArgsConstructor; - import org.springframework.stereotype.Component; import org.springframework.web.filter.OncePerRequestFilter; diff --git a/src/main/java/com/amorgakco/backend/group/controller/GroupController.java b/src/main/java/com/amorgakco/backend/group/controller/GroupController.java index 4ec9b3a..ea54123 100644 --- a/src/main/java/com/amorgakco/backend/group/controller/GroupController.java +++ b/src/main/java/com/amorgakco/backend/group/controller/GroupController.java @@ -8,11 +8,16 @@ import com.amorgakco.backend.group.dto.GroupRegisterRequest; import com.amorgakco.backend.group.service.GroupService; import com.amorgakco.backend.member.domain.Member; - import lombok.RequiredArgsConstructor; - import org.springframework.http.HttpStatus; -import org.springframework.web.bind.annotation.*; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("/groups") diff --git a/src/main/java/com/amorgakco/backend/group/controller/GroupLocationController.java b/src/main/java/com/amorgakco/backend/group/controller/GroupLocationController.java index 486c8c3..4e075e6 100644 --- a/src/main/java/com/amorgakco/backend/group/controller/GroupLocationController.java +++ b/src/main/java/com/amorgakco/backend/group/controller/GroupLocationController.java @@ -3,9 +3,7 @@ import com.amorgakco.backend.group.dto.GroupSearchRequest; import com.amorgakco.backend.group.dto.GroupSearchResponse; import com.amorgakco.backend.group.service.GroupLocationService; - import lombok.RequiredArgsConstructor; - import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.RequestMapping; diff --git a/src/main/java/com/amorgakco/backend/group/domain/Duration.java b/src/main/java/com/amorgakco/backend/group/domain/Duration.java index aaaab13..f5fc865 100644 --- a/src/main/java/com/amorgakco/backend/group/domain/Duration.java +++ b/src/main/java/com/amorgakco/backend/group/domain/Duration.java @@ -1,9 +1,7 @@ package com.amorgakco.backend.group.domain; import com.amorgakco.backend.global.exception.IllegalTimeException; - import jakarta.persistence.Embeddable; - import lombok.AccessLevel; import lombok.Getter; import lombok.NoArgsConstructor; diff --git a/src/main/java/com/amorgakco/backend/group/domain/Group.java b/src/main/java/com/amorgakco/backend/group/domain/Group.java index 1989ecd..e419573 100644 --- a/src/main/java/com/amorgakco/backend/group/domain/Group.java +++ b/src/main/java/com/amorgakco/backend/group/domain/Group.java @@ -4,10 +4,18 @@ import com.amorgakco.backend.global.exception.IllegalAccessException; import com.amorgakco.backend.group.domain.location.Location; import com.amorgakco.backend.member.domain.Member; +import com.amorgakco.backend.participant.domain.LocationVerificationStatus; import com.amorgakco.backend.participant.domain.Participant; - -import jakarta.persistence.*; - +import jakarta.persistence.CascadeType; +import jakarta.persistence.Embedded; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.Id; +import jakarta.persistence.Index; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.OneToMany; +import jakarta.persistence.Table; import lombok.AccessLevel; import lombok.Builder; import lombok.Getter; @@ -27,15 +35,22 @@ public class Group extends BaseTime { @OneToMany(mappedBy = "group", cascade = CascadeType.ALL) private final Set participants = new HashSet<>(); - @Id @GeneratedValue private Long id; + + @Id + @GeneratedValue + private Long id; private String name; private String description; private int groupCapacity; private String address; - @Embedded private Duration duration; + @Embedded + private Duration duration; + @ManyToOne(fetch = FetchType.LAZY) private Member host; - @Embedded private Location location; + + @Embedded + private Location location; @Builder public Group( @@ -53,6 +68,7 @@ public Group( this.groupCapacity = groupCapacity; this.duration = new Duration(beginAt, endAt); this.location = new Location(longitude, latitude); + this.participants.add(new Participant(host)); this.host = host; this.address = address; } @@ -75,13 +91,20 @@ private void validateDuplicatedParticipant(final Participant participant) { } private void validateGroupCapacity() { - if (groupCapacity == getCurrentGroupSize()) { + if (groupCapacity==getCurrentGroupSize()) { throw IllegalAccessException.exceedGroupCapacity(); } } public int getCurrentGroupSize() { - return participants.size() + 1; + return participants.size(); + } + + public boolean isEveryParticipantsVerified() { + long verifiedParticipants = participants.stream() + .filter(p -> p.getLocationVerificationStatus().equals(LocationVerificationStatus.VERIFIED)) + .count(); + return verifiedParticipants==participants.size(); } public boolean isNotGroupHost(final Long hostId) { diff --git a/src/main/java/com/amorgakco/backend/group/domain/location/Location.java b/src/main/java/com/amorgakco/backend/group/domain/location/Location.java index 956a13c..9c4bee0 100644 --- a/src/main/java/com/amorgakco/backend/group/domain/location/Location.java +++ b/src/main/java/com/amorgakco/backend/group/domain/location/Location.java @@ -4,9 +4,7 @@ import com.google.common.geometry.S2CellId; import com.google.common.geometry.S2LatLng; import com.google.common.geometry.S2Point; - import jakarta.persistence.Embeddable; - import lombok.AccessLevel; import lombok.Getter; import lombok.NoArgsConstructor; diff --git a/src/main/java/com/amorgakco/backend/group/domain/location/LocationCalculator.java b/src/main/java/com/amorgakco/backend/group/domain/location/LocationCalculator.java index aaeaf38..0ff871e 100644 --- a/src/main/java/com/amorgakco/backend/group/domain/location/LocationCalculator.java +++ b/src/main/java/com/amorgakco/backend/group/domain/location/LocationCalculator.java @@ -19,9 +19,9 @@ public static double getDistance( final double haversine = Math.sin(deltaLatitude / 2) * Math.sin(deltaLatitude / 2) + Math.cos(Math.toRadians(sourceLatitude)) - * Math.cos(Math.toRadians(targetLatitude)) - * Math.sin(deltaLongitude / 2) - * Math.sin(deltaLatitude / 2); + * Math.cos(Math.toRadians(targetLatitude)) + * Math.sin(deltaLongitude / 2) + * Math.sin(deltaLatitude / 2); return EARTH_RADIUS * 2 * Math.atan2(Math.sqrt(haversine), Math.sqrt(1 - haversine)) diff --git a/src/main/java/com/amorgakco/backend/group/dto/GroupBasicResponse.java b/src/main/java/com/amorgakco/backend/group/dto/GroupBasicResponse.java index 36d6098..67899a3 100644 --- a/src/main/java/com/amorgakco/backend/group/dto/GroupBasicResponse.java +++ b/src/main/java/com/amorgakco/backend/group/dto/GroupBasicResponse.java @@ -12,4 +12,5 @@ public record GroupBasicResponse( LocalDateTime endAt, int groupCapacity, int currentParticipants, - String address) {} + String address) { +} diff --git a/src/main/java/com/amorgakco/backend/group/dto/GroupDetailResponse.java b/src/main/java/com/amorgakco/backend/group/dto/GroupDetailResponse.java index 7dd9d1f..34110fe 100644 --- a/src/main/java/com/amorgakco/backend/group/dto/GroupDetailResponse.java +++ b/src/main/java/com/amorgakco/backend/group/dto/GroupDetailResponse.java @@ -15,4 +15,5 @@ public record GroupDetailResponse( double latitude, LocalDateTime beginAt, LocalDateTime endAt, - List groupMembers) {} + List groupMembers) { +} diff --git a/src/main/java/com/amorgakco/backend/group/dto/GroupLocation.java b/src/main/java/com/amorgakco/backend/group/dto/GroupLocation.java index 6150f8e..6cb09ab 100644 --- a/src/main/java/com/amorgakco/backend/group/dto/GroupLocation.java +++ b/src/main/java/com/amorgakco/backend/group/dto/GroupLocation.java @@ -3,4 +3,5 @@ import lombok.Builder; @Builder -public record GroupLocation(double latitude, double longitude, Long groupId) {} +public record GroupLocation(double latitude, double longitude, Long groupId) { +} diff --git a/src/main/java/com/amorgakco/backend/group/dto/GroupMember.java b/src/main/java/com/amorgakco/backend/group/dto/GroupMember.java index 76c8faf..62f5d6a 100644 --- a/src/main/java/com/amorgakco/backend/group/dto/GroupMember.java +++ b/src/main/java/com/amorgakco/backend/group/dto/GroupMember.java @@ -8,4 +8,5 @@ public record GroupMember( String imgUrl, String nickname, Integer moGakCoTemperature, - String githubUrl) {} + String githubUrl) { +} diff --git a/src/main/java/com/amorgakco/backend/group/dto/GroupRegisterRequest.java b/src/main/java/com/amorgakco/backend/group/dto/GroupRegisterRequest.java index e9744ea..82b5c4c 100644 --- a/src/main/java/com/amorgakco/backend/group/dto/GroupRegisterRequest.java +++ b/src/main/java/com/amorgakco/backend/group/dto/GroupRegisterRequest.java @@ -1,7 +1,6 @@ package com.amorgakco.backend.group.dto; import lombok.Builder; - import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDateTime; @@ -15,4 +14,5 @@ public record GroupRegisterRequest( @DateTimeFormat(pattern = "yyyy-MM-ddTHH:mm:ss") LocalDateTime endAt, double latitude, double longitude, - String address) {} + String address) { +} diff --git a/src/main/java/com/amorgakco/backend/group/dto/GroupSearchRequest.java b/src/main/java/com/amorgakco/backend/group/dto/GroupSearchRequest.java index a3b1d12..79aaa29 100644 --- a/src/main/java/com/amorgakco/backend/group/dto/GroupSearchRequest.java +++ b/src/main/java/com/amorgakco/backend/group/dto/GroupSearchRequest.java @@ -9,4 +9,5 @@ public record GroupSearchRequest( double northEastLat, double northEastLon, double centerLat, - double centerLon) {} + double centerLon) { +} diff --git a/src/main/java/com/amorgakco/backend/group/dto/GroupSearchResponse.java b/src/main/java/com/amorgakco/backend/group/dto/GroupSearchResponse.java index 74a1956..0d833f6 100644 --- a/src/main/java/com/amorgakco/backend/group/dto/GroupSearchResponse.java +++ b/src/main/java/com/amorgakco/backend/group/dto/GroupSearchResponse.java @@ -5,4 +5,5 @@ import java.util.List; @Builder -public record GroupSearchResponse(List locations) {} +public record GroupSearchResponse(List locations) { +} diff --git a/src/main/java/com/amorgakco/backend/group/dto/LocationVerificationRequest.java b/src/main/java/com/amorgakco/backend/group/dto/LocationVerificationRequest.java index fa5072a..32f3e08 100644 --- a/src/main/java/com/amorgakco/backend/group/dto/LocationVerificationRequest.java +++ b/src/main/java/com/amorgakco/backend/group/dto/LocationVerificationRequest.java @@ -1,3 +1,4 @@ package com.amorgakco.backend.group.dto; -public record LocationVerificationRequest(Long groupId, double latitude, double longitude) {} +public record LocationVerificationRequest(Long groupId, double latitude, double longitude) { +} diff --git a/src/main/java/com/amorgakco/backend/group/repository/GroupRepository.java b/src/main/java/com/amorgakco/backend/group/repository/GroupRepository.java index 1b9aa7d..2e7be25 100644 --- a/src/main/java/com/amorgakco/backend/group/repository/GroupRepository.java +++ b/src/main/java/com/amorgakco/backend/group/repository/GroupRepository.java @@ -1,7 +1,6 @@ package com.amorgakco.backend.group.repository; import com.amorgakco.backend.group.domain.Group; - import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.stereotype.Repository; diff --git a/src/main/java/com/amorgakco/backend/group/service/GroupService.java b/src/main/java/com/amorgakco/backend/group/service/GroupService.java index 37047c6..11ca0b8 100644 --- a/src/main/java/com/amorgakco/backend/group/service/GroupService.java +++ b/src/main/java/com/amorgakco/backend/group/service/GroupService.java @@ -10,9 +10,7 @@ import com.amorgakco.backend.group.repository.GroupRepository; import com.amorgakco.backend.group.service.mapper.GroupMapper; import com.amorgakco.backend.member.domain.Member; - import lombok.RequiredArgsConstructor; - import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; diff --git a/src/main/java/com/amorgakco/backend/group/service/S2GroupLocationService.java b/src/main/java/com/amorgakco/backend/group/service/S2GroupLocationService.java index e2ba58e..8529ff9 100644 --- a/src/main/java/com/amorgakco/backend/group/service/S2GroupLocationService.java +++ b/src/main/java/com/amorgakco/backend/group/service/S2GroupLocationService.java @@ -5,9 +5,7 @@ import com.amorgakco.backend.group.repository.GroupRepository; import com.amorgakco.backend.group.service.mapper.GroupMapper; import com.amorgakco.backend.group.service.search.S2CellSearch; - import lombok.RequiredArgsConstructor; - import org.springframework.stereotype.Service; import java.util.List; diff --git a/src/main/java/com/amorgakco/backend/group/service/mapper/GroupMapper.java b/src/main/java/com/amorgakco/backend/group/service/mapper/GroupMapper.java index e9f2a9e..2472c6d 100644 --- a/src/main/java/com/amorgakco/backend/group/service/mapper/GroupMapper.java +++ b/src/main/java/com/amorgakco/backend/group/service/mapper/GroupMapper.java @@ -8,7 +8,6 @@ import com.amorgakco.backend.group.dto.GroupMember; import com.amorgakco.backend.group.dto.GroupRegisterRequest; import com.amorgakco.backend.member.domain.Member; - import org.springframework.stereotype.Component; import java.util.List; diff --git a/src/main/java/com/amorgakco/backend/group/service/search/CityLevelSearchStrategy.java b/src/main/java/com/amorgakco/backend/group/service/search/CityLevelSearchStrategy.java index cc5a6f4..6545f46 100644 --- a/src/main/java/com/amorgakco/backend/group/service/search/CityLevelSearchStrategy.java +++ b/src/main/java/com/amorgakco/backend/group/service/search/CityLevelSearchStrategy.java @@ -3,7 +3,6 @@ import com.amorgakco.backend.group.dto.GroupSearchRequest; import com.google.common.geometry.S2LatLng; import com.google.common.geometry.S2LatLngRect; - import org.springframework.stereotype.Component; @Component diff --git a/src/main/java/com/amorgakco/backend/group/service/search/DongLevelSearchStrategy.java b/src/main/java/com/amorgakco/backend/group/service/search/DongLevelSearchStrategy.java index 21393c1..68505bb 100644 --- a/src/main/java/com/amorgakco/backend/group/service/search/DongLevelSearchStrategy.java +++ b/src/main/java/com/amorgakco/backend/group/service/search/DongLevelSearchStrategy.java @@ -1,7 +1,6 @@ package com.amorgakco.backend.group.service.search; import com.amorgakco.backend.group.dto.GroupSearchRequest; - import org.springframework.stereotype.Component; import java.util.List; diff --git a/src/main/java/com/amorgakco/backend/group/service/search/GroupSearchStrategy.java b/src/main/java/com/amorgakco/backend/group/service/search/GroupSearchStrategy.java index f26b442..18c90e0 100644 --- a/src/main/java/com/amorgakco/backend/group/service/search/GroupSearchStrategy.java +++ b/src/main/java/com/amorgakco/backend/group/service/search/GroupSearchStrategy.java @@ -14,10 +14,9 @@ public abstract class GroupSearchStrategy { public abstract boolean isValid(double diagonalSize); - public S2LatLngRect createRectangle(final GroupSearchRequest request) { - return S2LatLngRect.fromPointPair( - S2LatLng.fromDegrees(request.southWestLat(), request.southWestLon()), - S2LatLng.fromDegrees(request.northEastLat(), request.northEastLon())); + public List selectCellTokens(final GroupSearchRequest request) { + final List cellTokens = getCoveringCells(request); + return findHalfOfCells(cellTokens); } protected final List getCoveringCells(final GroupSearchRequest request) { @@ -32,15 +31,16 @@ protected final List getCoveringCells(final GroupSearchRequest request) return cellIds.stream().map(S2CellId::toToken).toList(); } - public List selectCellTokens(final GroupSearchRequest request) { - final List cellTokens = getCoveringCells(request); - return findHalfOfCells(cellTokens); - } - private List findHalfOfCells(final List cellTokens) { return IntStream.range(0, cellTokens.size() - 1) - .filter(i -> i % 2 == 0) + .filter(i -> i % 2==0) .mapToObj(cellTokens::get) .toList(); } + + public S2LatLngRect createRectangle(final GroupSearchRequest request) { + return S2LatLngRect.fromPointPair( + S2LatLng.fromDegrees(request.southWestLat(), request.southWestLon()), + S2LatLng.fromDegrees(request.northEastLat(), request.northEastLon())); + } } diff --git a/src/main/java/com/amorgakco/backend/group/service/search/S2CellSearch.java b/src/main/java/com/amorgakco/backend/group/service/search/S2CellSearch.java index 4079185..cd3c815 100644 --- a/src/main/java/com/amorgakco/backend/group/service/search/S2CellSearch.java +++ b/src/main/java/com/amorgakco/backend/group/service/search/S2CellSearch.java @@ -3,9 +3,7 @@ import com.amorgakco.backend.global.exception.IllegalAccessException; import com.amorgakco.backend.group.domain.location.LocationCalculator; import com.amorgakco.backend.group.dto.GroupSearchRequest; - import lombok.RequiredArgsConstructor; - import org.springframework.stereotype.Component; import java.util.List; @@ -22,13 +20,6 @@ public List getCellTokens(final GroupSearchRequest request) { return groupSearchStrategy.selectCellTokens(request); } - private GroupSearchStrategy getSearchStrategy(final double diagonalDistance) { - return searchStrategies.stream() - .filter(s -> s.isValid(diagonalDistance)) - .findFirst() - .orElseThrow(IllegalAccessException::invalidDiagonalDistance); - } - private double getDiagonalDistance(final GroupSearchRequest request) { return LocationCalculator.getDistance( request.southWestLon(), @@ -36,4 +27,11 @@ private double getDiagonalDistance(final GroupSearchRequest request) { request.northEastLon(), request.northEastLat()); } + + private GroupSearchStrategy getSearchStrategy(final double diagonalDistance) { + return searchStrategies.stream() + .filter(s -> s.isValid(diagonalDistance)) + .findFirst() + .orElseThrow(IllegalAccessException::invalidDiagonalDistance); + } } diff --git a/src/main/java/com/amorgakco/backend/groupparticipation/controller/GroupParticipationController.java b/src/main/java/com/amorgakco/backend/groupparticipation/controller/GroupParticipationController.java index 1f51ffb..569f2a5 100644 --- a/src/main/java/com/amorgakco/backend/groupparticipation/controller/GroupParticipationController.java +++ b/src/main/java/com/amorgakco/backend/groupparticipation/controller/GroupParticipationController.java @@ -1,11 +1,10 @@ package com.amorgakco.backend.groupparticipation.controller; import com.amorgakco.backend.global.argumentresolver.AuthMember; +import com.amorgakco.backend.global.argumentresolver.AuthMemberId; import com.amorgakco.backend.groupparticipation.service.GroupParticipationService; import com.amorgakco.backend.member.domain.Member; - import lombok.RequiredArgsConstructor; - import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.PatchMapping; import org.springframework.web.bind.annotation.PathVariable; @@ -23,8 +22,8 @@ public class GroupParticipationController { @PostMapping("/{groupId}/participation") @ResponseStatus(HttpStatus.CREATED) - public void participate(@PathVariable final Long groupId, @AuthMember final Member member) { - groupParticipationService.participate(groupId, member); + public void participate(@PathVariable final Long groupId, @AuthMemberId final Long memberId) { + groupParticipationService.participate(groupId, memberId); } @PostMapping("/{groupId}/participation/{memberId}") @@ -41,7 +40,7 @@ public void approve( public void reject( @PathVariable final Long groupId, @PathVariable final Long memberId, - @AuthMember final Member host) { - groupParticipationService.reject(groupId, memberId, host); + @AuthMemberId final Long hostId) { + groupParticipationService.reject(groupId, memberId, hostId); } } diff --git a/src/main/java/com/amorgakco/backend/groupparticipation/domain/GroupParticipation.java b/src/main/java/com/amorgakco/backend/groupparticipation/domain/GroupParticipation.java index 02b2d1d..1d986c6 100644 --- a/src/main/java/com/amorgakco/backend/groupparticipation/domain/GroupParticipation.java +++ b/src/main/java/com/amorgakco/backend/groupparticipation/domain/GroupParticipation.java @@ -5,7 +5,6 @@ import com.amorgakco.backend.group.domain.Group; import com.amorgakco.backend.member.domain.Member; import com.amorgakco.backend.participant.domain.Participant; - import jakarta.persistence.Entity; import jakarta.persistence.EnumType; import jakarta.persistence.Enumerated; @@ -14,7 +13,6 @@ import jakarta.persistence.Id; import jakarta.persistence.JoinColumn; import jakarta.persistence.ManyToOne; - import lombok.AccessLevel; import lombok.Builder; import lombok.Getter; @@ -25,7 +23,9 @@ @NoArgsConstructor(access = AccessLevel.PROTECTED) public class GroupParticipation extends BaseTime { - @Id @GeneratedValue private Long id; + @Id + @GeneratedValue + private Long id; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn diff --git a/src/main/java/com/amorgakco/backend/groupparticipation/repository/GroupParticipationRepository.java b/src/main/java/com/amorgakco/backend/groupparticipation/repository/GroupParticipationRepository.java index 729d15c..d0f2be6 100644 --- a/src/main/java/com/amorgakco/backend/groupparticipation/repository/GroupParticipationRepository.java +++ b/src/main/java/com/amorgakco/backend/groupparticipation/repository/GroupParticipationRepository.java @@ -1,7 +1,6 @@ package com.amorgakco.backend.groupparticipation.repository; import com.amorgakco.backend.groupparticipation.domain.GroupParticipation; - import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; diff --git a/src/main/java/com/amorgakco/backend/groupparticipation/service/GroupParticipationService.java b/src/main/java/com/amorgakco/backend/groupparticipation/service/GroupParticipationService.java index 07b974e..dd33991 100644 --- a/src/main/java/com/amorgakco/backend/groupparticipation/service/GroupParticipationService.java +++ b/src/main/java/com/amorgakco/backend/groupparticipation/service/GroupParticipationService.java @@ -7,13 +7,11 @@ import com.amorgakco.backend.groupparticipation.repository.GroupParticipationRepository; import com.amorgakco.backend.groupparticipation.service.mapper.GroupParticipationMapper; import com.amorgakco.backend.member.domain.Member; -import com.amorgakco.backend.notification.infrastructure.NotificationPublisher; -import com.amorgakco.backend.notification.infrastructure.consumer.NotificationRequest; +import com.amorgakco.backend.member.service.MemberService; +import com.amorgakco.backend.notification.infrastructure.NotificationPublisherFacade; import com.amorgakco.backend.notification.service.NotificationCreator; import com.amorgakco.backend.participant.domain.Participant; - import lombok.RequiredArgsConstructor; - import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -25,43 +23,48 @@ public class GroupParticipationService { private final GroupParticipationRepository groupParticipationRepository; private final GroupService groupService; private final GroupParticipationMapper groupParticipationMapper; - private final NotificationPublisher notificationPublisher; + private final NotificationPublisherFacade notificationPublisherFacade; + private final MemberService memberService; @Transactional - public void participate(final Long groupId, final Member member) { + public void participate(final Long groupId, final Long memberId) { final Group group = groupService.getGroup(groupId); - group.validateParticipation(new Participant(member)); + final Member requestMember = memberService.getMember(memberId); + group.validateParticipation(new Participant(requestMember)); final GroupParticipation groupParticipation = - groupParticipationMapper.toGroupParticipation(group, member); + groupParticipationMapper.toGroupParticipation(group, requestMember); groupParticipationRepository.save(groupParticipation); - final NotificationRequest notificationRequest = - NotificationCreator.participationNotification(member, group.getHost()); - notificationPublisher.sendSmsAndFcmWebPush(notificationRequest); + notificationPublisherFacade.send(NotificationCreator.participationRequest( + requestMember, + group.getHost(), + group.getName() + )); } @Transactional public void approve(final Long groupId, final Long memberId, final Member host) { - final GroupParticipation groupParticipation = - groupParticipationRepository - .findByGroupIdAndMemberId(groupId, memberId) - .orElseThrow(ResourceNotFoundException::participationNotFound); + final GroupParticipation groupParticipation = getGroupParticipation(groupId, memberId); groupParticipation.approve(host); - final NotificationRequest notificationRequest = - NotificationCreator.participationApproveNotification( - host, groupParticipation.getParticipant()); - notificationPublisher.sendSmsAndFcmWebPush(notificationRequest); + notificationPublisherFacade.send(NotificationCreator.participationApprove( + memberService.getMember(memberId), + groupParticipation.getGroup().getName() + )); + } + + private GroupParticipation getGroupParticipation(final Long groupId, final Long memberId) { + return groupParticipationRepository + .findByGroupIdAndMemberId(groupId, memberId) + .orElseThrow(ResourceNotFoundException::participationNotFound); } @Transactional - public void reject(final Long groupId, final Long memberId, final Member host) { - final GroupParticipation groupParticipation = - groupParticipationRepository - .findByGroupIdAndMemberId(groupId, memberId) - .orElseThrow(ResourceNotFoundException::participationNotFound); - groupParticipation.reject(host); - final NotificationRequest notificationRequest = - NotificationCreator.participationRejectNotification( - host, groupParticipation.getParticipant()); - notificationPublisher.sendFcmWebPush(notificationRequest); + public void reject(final Long groupId, final Long memberId, final Long hostId) { + final GroupParticipation groupParticipation = getGroupParticipation(groupId, memberId); + final Member member = memberService.getMember(hostId); + groupParticipation.reject(memberService.getMember(hostId)); + notificationPublisherFacade.send(NotificationCreator.participationReject( + member, + groupParticipation.getGroup().getName() + )); } } diff --git a/src/main/java/com/amorgakco/backend/groupparticipation/service/mapper/GroupParticipationMapper.java b/src/main/java/com/amorgakco/backend/groupparticipation/service/mapper/GroupParticipationMapper.java index 02d2eb2..35c5f9a 100644 --- a/src/main/java/com/amorgakco/backend/groupparticipation/service/mapper/GroupParticipationMapper.java +++ b/src/main/java/com/amorgakco/backend/groupparticipation/service/mapper/GroupParticipationMapper.java @@ -3,7 +3,6 @@ import com.amorgakco.backend.group.domain.Group; import com.amorgakco.backend.groupparticipation.domain.GroupParticipation; import com.amorgakco.backend.member.domain.Member; - import org.springframework.stereotype.Component; @Component diff --git a/src/main/java/com/amorgakco/backend/jwt/controller/JwtController.java b/src/main/java/com/amorgakco/backend/jwt/controller/JwtController.java index 201c8bc..89d8b56 100644 --- a/src/main/java/com/amorgakco/backend/jwt/controller/JwtController.java +++ b/src/main/java/com/amorgakco/backend/jwt/controller/JwtController.java @@ -3,14 +3,16 @@ import com.amorgakco.backend.jwt.dto.AccessTokenResponse; import com.amorgakco.backend.jwt.dto.MemberTokens; import com.amorgakco.backend.jwt.service.JwtService; - import jakarta.servlet.http.Cookie; import jakarta.servlet.http.HttpServletResponse; - import lombok.RequiredArgsConstructor; - import org.springframework.http.HttpStatus; -import org.springframework.web.bind.annotation.*; +import org.springframework.web.bind.annotation.CookieValue; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestController; import java.util.Optional; diff --git a/src/main/java/com/amorgakco/backend/jwt/controller/JwtCookieLoader.java b/src/main/java/com/amorgakco/backend/jwt/controller/JwtCookieLoader.java index 356481f..3c87f43 100644 --- a/src/main/java/com/amorgakco/backend/jwt/controller/JwtCookieLoader.java +++ b/src/main/java/com/amorgakco/backend/jwt/controller/JwtCookieLoader.java @@ -1,7 +1,6 @@ package com.amorgakco.backend.jwt.controller; import jakarta.servlet.http.HttpServletResponse; - import org.springframework.http.HttpHeaders; import org.springframework.http.ResponseCookie; import org.springframework.stereotype.Component; diff --git a/src/main/java/com/amorgakco/backend/jwt/domain/RefreshToken.java b/src/main/java/com/amorgakco/backend/jwt/domain/RefreshToken.java index f867a97..8f465b4 100644 --- a/src/main/java/com/amorgakco/backend/jwt/domain/RefreshToken.java +++ b/src/main/java/com/amorgakco/backend/jwt/domain/RefreshToken.java @@ -2,7 +2,6 @@ import lombok.AllArgsConstructor; import lombok.Getter; - import org.springframework.data.annotation.Id; import org.springframework.data.redis.core.RedisHash; @@ -11,7 +10,8 @@ @RedisHash(value = "blackToken", timeToLive = 604800) public class RefreshToken { - @Id private String token; + @Id + private String token; private String memberId; } diff --git a/src/main/java/com/amorgakco/backend/jwt/dto/AccessTokenResponse.java b/src/main/java/com/amorgakco/backend/jwt/dto/AccessTokenResponse.java index e7d6be2..fabf91c 100644 --- a/src/main/java/com/amorgakco/backend/jwt/dto/AccessTokenResponse.java +++ b/src/main/java/com/amorgakco/backend/jwt/dto/AccessTokenResponse.java @@ -1,3 +1,4 @@ package com.amorgakco.backend.jwt.dto; -public record AccessTokenResponse(String accessToken) {} +public record AccessTokenResponse(String accessToken) { +} diff --git a/src/main/java/com/amorgakco/backend/jwt/dto/MemberAccessToken.java b/src/main/java/com/amorgakco/backend/jwt/dto/MemberAccessToken.java index d9534e0..4a9bbb5 100644 --- a/src/main/java/com/amorgakco/backend/jwt/dto/MemberAccessToken.java +++ b/src/main/java/com/amorgakco/backend/jwt/dto/MemberAccessToken.java @@ -1,3 +1,4 @@ package com.amorgakco.backend.jwt.dto; -public record MemberAccessToken(String accessToken, String memberId) {} +public record MemberAccessToken(String accessToken, String memberId) { +} diff --git a/src/main/java/com/amorgakco/backend/jwt/dto/MemberTokens.java b/src/main/java/com/amorgakco/backend/jwt/dto/MemberTokens.java index 928bf46..233648a 100644 --- a/src/main/java/com/amorgakco/backend/jwt/dto/MemberTokens.java +++ b/src/main/java/com/amorgakco/backend/jwt/dto/MemberTokens.java @@ -1,3 +1,4 @@ package com.amorgakco.backend.jwt.dto; -public record MemberTokens(String accessToken, String refreshToken) {} +public record MemberTokens(String accessToken, String refreshToken) { +} diff --git a/src/main/java/com/amorgakco/backend/jwt/repository/RefreshTokenRepository.java b/src/main/java/com/amorgakco/backend/jwt/repository/RefreshTokenRepository.java index 185a2a2..b7e9803 100644 --- a/src/main/java/com/amorgakco/backend/jwt/repository/RefreshTokenRepository.java +++ b/src/main/java/com/amorgakco/backend/jwt/repository/RefreshTokenRepository.java @@ -1,9 +1,9 @@ package com.amorgakco.backend.jwt.repository; import com.amorgakco.backend.jwt.domain.RefreshToken; - import org.springframework.data.repository.CrudRepository; import org.springframework.stereotype.Repository; @Repository -public interface RefreshTokenRepository extends CrudRepository {} +public interface RefreshTokenRepository extends CrudRepository { +} diff --git a/src/main/java/com/amorgakco/backend/jwt/service/JwtCreator.java b/src/main/java/com/amorgakco/backend/jwt/service/JwtCreator.java index 45eca14..1301ea7 100644 --- a/src/main/java/com/amorgakco/backend/jwt/service/JwtCreator.java +++ b/src/main/java/com/amorgakco/backend/jwt/service/JwtCreator.java @@ -1,14 +1,11 @@ package com.amorgakco.backend.jwt.service; import io.jsonwebtoken.Jwts; - import lombok.RequiredArgsConstructor; - import org.springframework.stereotype.Component; -import java.util.Date; - import javax.crypto.SecretKey; +import java.util.Date; @Component @RequiredArgsConstructor diff --git a/src/main/java/com/amorgakco/backend/jwt/service/JwtProperties.java b/src/main/java/com/amorgakco/backend/jwt/service/JwtProperties.java index c0e6d17..c4b1f57 100644 --- a/src/main/java/com/amorgakco/backend/jwt/service/JwtProperties.java +++ b/src/main/java/com/amorgakco/backend/jwt/service/JwtProperties.java @@ -3,4 +3,5 @@ import org.springframework.boot.context.properties.ConfigurationProperties; @ConfigurationProperties(prefix = "jwt") -public record JwtProperties(Long accessExpiration, Long refreshExpiration, String frontUrl) {} +public record JwtProperties(Long accessExpiration, Long refreshExpiration, String frontUrl) { +} diff --git a/src/main/java/com/amorgakco/backend/jwt/service/JwtService.java b/src/main/java/com/amorgakco/backend/jwt/service/JwtService.java index c7bdbd9..86d67c1 100644 --- a/src/main/java/com/amorgakco/backend/jwt/service/JwtService.java +++ b/src/main/java/com/amorgakco/backend/jwt/service/JwtService.java @@ -1,15 +1,12 @@ package com.amorgakco.backend.jwt.service; -import com.amorgakco.backend.global.exception.*; import com.amorgakco.backend.global.exception.IllegalAccessException; +import com.amorgakco.backend.global.exception.ResourceNotFoundException; import com.amorgakco.backend.jwt.domain.RefreshToken; import com.amorgakco.backend.jwt.dto.MemberTokens; import com.amorgakco.backend.jwt.repository.RefreshTokenRepository; - import jakarta.servlet.http.Cookie; - import lombok.RequiredArgsConstructor; - import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; diff --git a/src/main/java/com/amorgakco/backend/jwt/service/JwtValidator.java b/src/main/java/com/amorgakco/backend/jwt/service/JwtValidator.java index e90f408..c625635 100644 --- a/src/main/java/com/amorgakco/backend/jwt/service/JwtValidator.java +++ b/src/main/java/com/amorgakco/backend/jwt/service/JwtValidator.java @@ -1,25 +1,21 @@ package com.amorgakco.backend.jwt.service; -import com.amorgakco.backend.global.exception.*; +import com.amorgakco.backend.global.exception.JwtAuthenticationException; import com.amorgakco.backend.global.oauth.MemberPrincipal; import com.amorgakco.backend.member.domain.Member; import com.amorgakco.backend.member.repository.MemberRepository; - import io.jsonwebtoken.ExpiredJwtException; import io.jsonwebtoken.JwtException; import io.jsonwebtoken.Jwts; - import lombok.RequiredArgsConstructor; - import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.AuthorityUtils; import org.springframework.stereotype.Component; -import java.util.List; - import javax.crypto.SecretKey; +import java.util.List; @Component @RequiredArgsConstructor diff --git a/src/main/java/com/amorgakco/backend/member/controller/MemberController.java b/src/main/java/com/amorgakco/backend/member/controller/MemberController.java index 42f1441..44c0127 100644 --- a/src/main/java/com/amorgakco/backend/member/controller/MemberController.java +++ b/src/main/java/com/amorgakco/backend/member/controller/MemberController.java @@ -4,9 +4,7 @@ import com.amorgakco.backend.member.dto.AdditionalInfoRequest; import com.amorgakco.backend.member.dto.PrivateMemberResponse; import com.amorgakco.backend.member.service.MemberService; - import lombok.RequiredArgsConstructor; - import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PatchMapping; diff --git a/src/main/java/com/amorgakco/backend/member/domain/Member.java b/src/main/java/com/amorgakco/backend/member/domain/Member.java index ef285bc..8666ed1 100644 --- a/src/main/java/com/amorgakco/backend/member/domain/Member.java +++ b/src/main/java/com/amorgakco/backend/member/domain/Member.java @@ -1,11 +1,21 @@ package com.amorgakco.backend.member.domain; import com.amorgakco.backend.global.BaseTime; +import com.amorgakco.backend.global.exception.IllegalAccessException; import com.amorgakco.backend.global.exception.IllegalFormatException; - -import jakarta.persistence.*; - -import lombok.*; +import jakarta.persistence.CascadeType; +import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.OneToMany; +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; import java.util.ArrayList; import java.util.List; @@ -16,7 +26,12 @@ public class Member extends BaseTime { private static final String HTTPS_GITHUB_PREFIX = "https://github"; private static final String GITHUB_PREFIX = "github"; - @Id @GeneratedValue private Long id; + private static final Integer MAX_MOGAKCO_TEMPERATURE = 100; + private static final Integer MIN_MOGAKCO_TEMPERATURE = -100; + + @Id + @GeneratedValue + private Long id; @Enumerated(EnumType.STRING) private Oauth2ProviderType oauth2ProviderType; @@ -32,7 +47,7 @@ public class Member extends BaseTime { @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY) @JoinColumn(name = "member_id") - private List roleNames = new ArrayList<>(); + private final List roleNames = new ArrayList<>(); @Builder public Member( @@ -79,6 +94,20 @@ private void validatePhoneNumber(final String phoneNumber) { } } + public Integer upMoGakCoTemperature() { + if (moGakCoTemperature + 1 > MAX_MOGAKCO_TEMPERATURE) { + throw IllegalAccessException.canNotExceedPositive100(); + } + return ++moGakCoTemperature; + } + + public Integer downMoGakCoTemperature() { + if (moGakCoTemperature - 1 < MIN_MOGAKCO_TEMPERATURE) { + throw IllegalAccessException.canNotUnderNegative100(); + } + return --moGakCoTemperature; + } + public boolean isEquals(final Long memberId) { return this.id.equals(memberId); } diff --git a/src/main/java/com/amorgakco/backend/member/domain/Roles.java b/src/main/java/com/amorgakco/backend/member/domain/Roles.java index 10ace69..55b6664 100644 --- a/src/main/java/com/amorgakco/backend/member/domain/Roles.java +++ b/src/main/java/com/amorgakco/backend/member/domain/Roles.java @@ -1,7 +1,11 @@ package com.amorgakco.backend.member.domain; -import jakarta.persistence.*; - +import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; import lombok.AccessLevel; import lombok.Getter; import lombok.NoArgsConstructor; diff --git a/src/main/java/com/amorgakco/backend/member/dto/AdditionalInfoRequest.java b/src/main/java/com/amorgakco/backend/member/dto/AdditionalInfoRequest.java index 61b2c8f..c5b0235 100644 --- a/src/main/java/com/amorgakco/backend/member/dto/AdditionalInfoRequest.java +++ b/src/main/java/com/amorgakco/backend/member/dto/AdditionalInfoRequest.java @@ -8,4 +8,5 @@ public record AdditionalInfoRequest( String phoneNumber, boolean smsNotificationSetting, double longitude, - double latitude) {} + double latitude) { +} diff --git a/src/main/java/com/amorgakco/backend/member/dto/PrivateMemberResponse.java b/src/main/java/com/amorgakco/backend/member/dto/PrivateMemberResponse.java index a07de99..1b121c7 100644 --- a/src/main/java/com/amorgakco/backend/member/dto/PrivateMemberResponse.java +++ b/src/main/java/com/amorgakco/backend/member/dto/PrivateMemberResponse.java @@ -7,4 +7,5 @@ public record PrivateMemberResponse( boolean smsNotificationSetting, String githubUrl, String phoneNumber, - Integer moGakCoTemperature) {} + Integer moGakCoTemperature) { +} diff --git a/src/main/java/com/amorgakco/backend/member/repository/MemberRepository.java b/src/main/java/com/amorgakco/backend/member/repository/MemberRepository.java index 3a85b51..066ef4b 100644 --- a/src/main/java/com/amorgakco/backend/member/repository/MemberRepository.java +++ b/src/main/java/com/amorgakco/backend/member/repository/MemberRepository.java @@ -2,7 +2,6 @@ import com.amorgakco.backend.member.domain.Member; import com.amorgakco.backend.member.domain.Oauth2ProviderType; - import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.stereotype.Repository; diff --git a/src/main/java/com/amorgakco/backend/member/service/MemberService.java b/src/main/java/com/amorgakco/backend/member/service/MemberService.java index 2ce14cc..49ca4a2 100644 --- a/src/main/java/com/amorgakco/backend/member/service/MemberService.java +++ b/src/main/java/com/amorgakco/backend/member/service/MemberService.java @@ -11,9 +11,7 @@ import com.google.common.geometry.S2CellId; import com.google.common.geometry.S2LatLng; import com.google.common.geometry.S2Point; - import lombok.RequiredArgsConstructor; - import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; diff --git a/src/main/java/com/amorgakco/backend/member/service/mapper/MemberMapper.java b/src/main/java/com/amorgakco/backend/member/service/mapper/MemberMapper.java index 88cb1c8..78323fb 100644 --- a/src/main/java/com/amorgakco/backend/member/service/mapper/MemberMapper.java +++ b/src/main/java/com/amorgakco/backend/member/service/mapper/MemberMapper.java @@ -3,7 +3,6 @@ import com.amorgakco.backend.member.domain.Member; import com.amorgakco.backend.member.dto.PrivateMemberResponse; import com.amorgakco.backend.oauth2.provider.Oauth2Member; - import org.springframework.stereotype.Component; @Component diff --git a/src/main/java/com/amorgakco/backend/notification/controller/NotificationController.java b/src/main/java/com/amorgakco/backend/notification/controller/NotificationController.java index d2b5600..f9f8d8b 100644 --- a/src/main/java/com/amorgakco/backend/notification/controller/NotificationController.java +++ b/src/main/java/com/amorgakco/backend/notification/controller/NotificationController.java @@ -3,9 +3,7 @@ import com.amorgakco.backend.global.argumentresolver.AuthMemberId; import com.amorgakco.backend.notification.dto.NotificationMessageResponse; import com.amorgakco.backend.notification.service.NotificationService; - import lombok.RequiredArgsConstructor; - import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; diff --git a/src/main/java/com/amorgakco/backend/notification/domain/Notification.java b/src/main/java/com/amorgakco/backend/notification/domain/Notification.java index 501aa49..c72a9b2 100644 --- a/src/main/java/com/amorgakco/backend/notification/domain/Notification.java +++ b/src/main/java/com/amorgakco/backend/notification/domain/Notification.java @@ -2,7 +2,6 @@ import com.amorgakco.backend.global.BaseTime; import com.amorgakco.backend.member.domain.Member; - import jakarta.persistence.Entity; import jakarta.persistence.EnumType; import jakarta.persistence.Enumerated; @@ -10,7 +9,6 @@ import jakarta.persistence.GeneratedValue; import jakarta.persistence.Id; import jakarta.persistence.ManyToOne; - import lombok.AccessLevel; import lombok.Builder; import lombok.Getter; @@ -21,28 +19,29 @@ @NoArgsConstructor(access = AccessLevel.PROTECTED) public class Notification extends BaseTime { - @Id @GeneratedValue private Long id; + @Id + @GeneratedValue + private Long id; - @Enumerated(EnumType.STRING) - private NotificationTitle notificationTitle; - - @ManyToOne(fetch = FetchType.LAZY) - private Member sender; + private String title; @ManyToOne(fetch = FetchType.LAZY) private Member receiver; + @Enumerated(EnumType.STRING) + private SendingType sendingType; + private String content; @Builder public Notification( - final NotificationTitle notificationTitle, - final Member sender, + final String title, + final String content, final Member receiver, - final String content) { - this.notificationTitle = notificationTitle; - this.sender = sender; - this.receiver = receiver; + final SendingType sendingType) { + this.title = title; this.content = content; + this.receiver = receiver; + this.sendingType = sendingType; } } diff --git a/src/main/java/com/amorgakco/backend/notification/domain/NotificationTitle.java b/src/main/java/com/amorgakco/backend/notification/domain/NotificationTitle.java deleted file mode 100644 index 2e29031..0000000 --- a/src/main/java/com/amorgakco/backend/notification/domain/NotificationTitle.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.amorgakco.backend.notification.domain; - -import lombok.Getter; -import lombok.RequiredArgsConstructor; - -@RequiredArgsConstructor -@Getter -public enum NotificationTitle { - PARTICIPATION_REQUEST("참여 요청"), - PARTICIPATION_APPROVED("참여 허가"), - PARTICIPATION_REJECTED("참여 거절"); - - private final String title; -} diff --git a/src/main/java/com/amorgakco/backend/notification/domain/NotificationType.java b/src/main/java/com/amorgakco/backend/notification/domain/NotificationType.java new file mode 100644 index 0000000..5bf2ac3 --- /dev/null +++ b/src/main/java/com/amorgakco/backend/notification/domain/NotificationType.java @@ -0,0 +1,16 @@ +package com.amorgakco.backend.notification.domain; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +@Getter +public enum NotificationType { + PARTICIPATION_REQUEST("참여 요청", "%s 님께서 %s 모각코에 참여하길 원합니다."), + PARTICIPATION_APPROVED("참여 허가", "%s 모각코 참여가 허가됐습니다."), + PARTICIPATION_REJECTED("참여 거절", "%s 모각코 참여가 거절됐습니다."), + PARTICIPATION_TARDINESS("모각코 지각", "%s 님께서 %s 모각코에 %d분 지각 알림을 보냈습니다."), + PARTICIPATION_WITHDRAW("모각코 탈퇴", "%s 님께서 %s 모각코를 탈퇴하셨습니다."); + private final String title; + private final String content; +} diff --git a/src/main/java/com/amorgakco/backend/notification/domain/SendingType.java b/src/main/java/com/amorgakco/backend/notification/domain/SendingType.java new file mode 100644 index 0000000..fee61d7 --- /dev/null +++ b/src/main/java/com/amorgakco/backend/notification/domain/SendingType.java @@ -0,0 +1,7 @@ +package com.amorgakco.backend.notification.domain; + +public enum SendingType { + SMS, + WEB_PUSH, + SMS_AND_WEB_PUSH, +} diff --git a/src/main/java/com/amorgakco/backend/notification/dto/NotificationMessage.java b/src/main/java/com/amorgakco/backend/notification/dto/NotificationMessage.java index 13201e3..5189838 100644 --- a/src/main/java/com/amorgakco/backend/notification/dto/NotificationMessage.java +++ b/src/main/java/com/amorgakco/backend/notification/dto/NotificationMessage.java @@ -3,4 +3,5 @@ import lombok.Builder; @Builder -public record NotificationMessage(String title, String content) {} +public record NotificationMessage(String title, String content) { +} diff --git a/src/main/java/com/amorgakco/backend/notification/dto/NotificationMessageResponse.java b/src/main/java/com/amorgakco/backend/notification/dto/NotificationMessageResponse.java index 0f1b99d..449ec65 100644 --- a/src/main/java/com/amorgakco/backend/notification/dto/NotificationMessageResponse.java +++ b/src/main/java/com/amorgakco/backend/notification/dto/NotificationMessageResponse.java @@ -9,4 +9,5 @@ public record NotificationMessageResponse( int page, int elementSize, boolean hasNext, - List notificationMessages) {} + List notificationMessages) { +} diff --git a/src/main/java/com/amorgakco/backend/notification/infrastructure/NotificationPublisherFacade.java b/src/main/java/com/amorgakco/backend/notification/infrastructure/NotificationPublisherFacade.java new file mode 100644 index 0000000..56008a0 --- /dev/null +++ b/src/main/java/com/amorgakco/backend/notification/infrastructure/NotificationPublisherFacade.java @@ -0,0 +1,32 @@ +package com.amorgakco.backend.notification.infrastructure; + +import com.amorgakco.backend.notification.domain.SendingType; +import com.amorgakco.backend.notification.infrastructure.consumer.NotificationRequest; +import com.amorgakco.backend.notification.infrastructure.publisher.FcmPublisher; +import com.amorgakco.backend.notification.infrastructure.publisher.Publisher; +import com.amorgakco.backend.notification.infrastructure.publisher.SmsAndFcmPublisher; +import com.amorgakco.backend.notification.infrastructure.publisher.SmsPublisher; +import org.springframework.stereotype.Service; + +import java.util.EnumMap; + +@Service +public class NotificationPublisherFacade { + + private final EnumMap publishers = new EnumMap<>(SendingType.class); + + public NotificationPublisherFacade( + final SmsPublisher smsPublisher, + final FcmPublisher fcmPublisher, + final SmsAndFcmPublisher smsAndFcmPublisher + ) { + publishers.put(SendingType.SMS, smsPublisher); + publishers.put(SendingType.WEB_PUSH, fcmPublisher); + publishers.put(SendingType.SMS_AND_WEB_PUSH, smsAndFcmPublisher); + } + + public void send(final NotificationRequest request) { + final Publisher publisher = publishers.get(request.sendingType()); + publisher.publish(request); + } +} diff --git a/src/main/java/com/amorgakco/backend/notification/infrastructure/consumer/NotificationRequest.java b/src/main/java/com/amorgakco/backend/notification/infrastructure/consumer/NotificationRequest.java index 0d9024f..b1cd115 100644 --- a/src/main/java/com/amorgakco/backend/notification/infrastructure/consumer/NotificationRequest.java +++ b/src/main/java/com/amorgakco/backend/notification/infrastructure/consumer/NotificationRequest.java @@ -1,10 +1,10 @@ package com.amorgakco.backend.notification.infrastructure.consumer; import com.amorgakco.backend.member.domain.Member; -import com.amorgakco.backend.notification.domain.NotificationTitle; - +import com.amorgakco.backend.notification.domain.SendingType; import lombok.Builder; @Builder public record NotificationRequest( - NotificationTitle notificationTitle, Member sender, Member receiver, String content) {} + String title, SendingType sendingType, String content, Member receiver) { +} diff --git a/src/main/java/com/amorgakco/backend/notification/infrastructure/consumer/fcm/FcmWebPushConsumer.java b/src/main/java/com/amorgakco/backend/notification/infrastructure/consumer/fcm/FcmWebPushConsumer.java index b2a5b32..793b073 100644 --- a/src/main/java/com/amorgakco/backend/notification/infrastructure/consumer/fcm/FcmWebPushConsumer.java +++ b/src/main/java/com/amorgakco/backend/notification/infrastructure/consumer/fcm/FcmWebPushConsumer.java @@ -1,14 +1,15 @@ package com.amorgakco.backend.notification.infrastructure.consumer.fcm; import com.amorgakco.backend.fcmtoken.repository.FcmTokenRepository; +import com.amorgakco.backend.notification.domain.Notification; import com.amorgakco.backend.notification.infrastructure.consumer.NotificationRequest; import com.amorgakco.backend.notification.infrastructure.consumer.slack.SlackSender; +import com.amorgakco.backend.notification.repository.NotificationRepository; +import com.amorgakco.backend.notification.service.mapper.NotificationMapper; import com.google.firebase.messaging.Message; import com.google.firebase.messaging.WebpushConfig; import com.google.firebase.messaging.WebpushNotification; - import lombok.RequiredArgsConstructor; - import org.springframework.amqp.rabbit.annotation.RabbitListener; import org.springframework.stereotype.Component; @@ -18,9 +19,13 @@ public class FcmWebPushConsumer { private final FcmTokenRepository fcmTokenRepository; private final SlackSender slackSender; + private final NotificationRepository notificationRepository; + private final NotificationMapper notificationMapper; @RabbitListener(queues = "fcm") public void send(final NotificationRequest request) { + final Notification notification = notificationMapper.toNotification(request); + notificationRepository.save(notification); slackSender.sendNotification(request); // fcmTokenRepository // .findById(request.receiver().getId().toString()) @@ -28,7 +33,7 @@ public void send(final NotificationRequest request) { // token -> // createMessage( // token.getToken(), - // request.notificationTitle().getTitle(), + // request.notificationContent().getTitle(), // request.content())); } diff --git a/src/main/java/com/amorgakco/backend/notification/infrastructure/consumer/slack/SlackRequest.java b/src/main/java/com/amorgakco/backend/notification/infrastructure/consumer/slack/SlackRequest.java index 308bddc..f8437a6 100644 --- a/src/main/java/com/amorgakco/backend/notification/infrastructure/consumer/slack/SlackRequest.java +++ b/src/main/java/com/amorgakco/backend/notification/infrastructure/consumer/slack/SlackRequest.java @@ -1,3 +1,4 @@ package com.amorgakco.backend.notification.infrastructure.consumer.slack; -public record SlackRequest(String text) {} +public record SlackRequest(String text) { +} diff --git a/src/main/java/com/amorgakco/backend/notification/infrastructure/consumer/slack/SlackSender.java b/src/main/java/com/amorgakco/backend/notification/infrastructure/consumer/slack/SlackSender.java index 2151dee..b9ff8cc 100644 --- a/src/main/java/com/amorgakco/backend/notification/infrastructure/consumer/slack/SlackSender.java +++ b/src/main/java/com/amorgakco/backend/notification/infrastructure/consumer/slack/SlackSender.java @@ -1,7 +1,6 @@ package com.amorgakco.backend.notification.infrastructure.consumer.slack; import com.amorgakco.backend.notification.infrastructure.consumer.NotificationRequest; - import org.springframework.beans.factory.annotation.Value; import org.springframework.http.MediaType; import org.springframework.stereotype.Component; diff --git a/src/main/java/com/amorgakco/backend/notification/infrastructure/consumer/sms/CoolSmsConsumer.java b/src/main/java/com/amorgakco/backend/notification/infrastructure/consumer/sms/CoolSmsConsumer.java index 7d80d86..514f471 100644 --- a/src/main/java/com/amorgakco/backend/notification/infrastructure/consumer/sms/CoolSmsConsumer.java +++ b/src/main/java/com/amorgakco/backend/notification/infrastructure/consumer/sms/CoolSmsConsumer.java @@ -1,12 +1,13 @@ package com.amorgakco.backend.notification.infrastructure.consumer.sms; import com.amorgakco.backend.member.domain.Member; +import com.amorgakco.backend.notification.domain.Notification; import com.amorgakco.backend.notification.infrastructure.consumer.NotificationRequest; import com.amorgakco.backend.notification.infrastructure.consumer.slack.SlackSender; - +import com.amorgakco.backend.notification.repository.NotificationRepository; +import com.amorgakco.backend.notification.service.mapper.NotificationMapper; import net.nurigo.sdk.message.model.Message; import net.nurigo.sdk.message.service.DefaultMessageService; - import org.springframework.amqp.rabbit.annotation.RabbitListener; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; @@ -17,19 +18,27 @@ public class CoolSmsConsumer implements SmsSender { private final DefaultMessageService messageService; private final String serverPhoneNumber; private final SlackSender slackSender; + private final NotificationRepository notificationRepository; + private final NotificationMapper notificationMapper; public CoolSmsConsumer( final DefaultMessageService messageService, @Value("${server-phone-number}") final String serverPhoneNumber, - final SlackSender slackSender) { + final SlackSender slackSender, + final NotificationMapper notificationMapper, + final NotificationRepository notificationRepository) { this.messageService = messageService; this.serverPhoneNumber = serverPhoneNumber; this.slackSender = slackSender; + this.notificationMapper = notificationMapper; + this.notificationRepository = notificationRepository; } @Override @RabbitListener(queues = "sms") public void send(final NotificationRequest request) { + final Notification notification = notificationMapper.toNotification(request); + notificationRepository.save(notification); slackSender.sendNotification(request); // final Message message = createMessage(request); // messageService.sendOne(new SingleMessageSendingRequest(message)); @@ -40,7 +49,7 @@ private Message createMessage(final NotificationRequest request) { final Member receiver = request.receiver(); message.setFrom(serverPhoneNumber); message.setTo(receiver.getPhoneNumber()); - message.setText(request.notificationTitle().getTitle() + "\n"); + message.setText(request.title() + "\n"); message.setText(request.content()); return message; } diff --git a/src/main/java/com/amorgakco/backend/notification/infrastructure/NotificationPublisher.java b/src/main/java/com/amorgakco/backend/notification/infrastructure/publisher/FcmPublisher.java similarity index 50% rename from src/main/java/com/amorgakco/backend/notification/infrastructure/NotificationPublisher.java rename to src/main/java/com/amorgakco/backend/notification/infrastructure/publisher/FcmPublisher.java index df86f3b..72b6aeb 100644 --- a/src/main/java/com/amorgakco/backend/notification/infrastructure/NotificationPublisher.java +++ b/src/main/java/com/amorgakco/backend/notification/infrastructure/publisher/FcmPublisher.java @@ -1,44 +1,22 @@ -package com.amorgakco.backend.notification.infrastructure; +package com.amorgakco.backend.notification.infrastructure.publisher; import com.amorgakco.backend.fcmtoken.repository.FcmTokenRepository; import com.amorgakco.backend.global.rabbitmq.ExchangeName; import com.amorgakco.backend.global.rabbitmq.RoutingKey; -import com.amorgakco.backend.notification.domain.Notification; import com.amorgakco.backend.notification.infrastructure.consumer.NotificationRequest; -import com.amorgakco.backend.notification.repository.NotificationRepository; -import com.amorgakco.backend.notification.service.mapper.NotificationMapper; - import lombok.RequiredArgsConstructor; - import org.springframework.amqp.rabbit.core.RabbitTemplate; -import org.springframework.stereotype.Service; +import org.springframework.stereotype.Component; -@Service +@Component @RequiredArgsConstructor -public class NotificationPublisher { +public class FcmPublisher implements Publisher { private final RabbitTemplate rabbitTemplate; private final FcmTokenRepository fcmTokenRepository; - private final NotificationRepository notificationRepository; - private final NotificationMapper notificationMapper; - - public void sendSmsAndFcmWebPush(final NotificationRequest request) { - sendSms(request); - sendFcmWebPush(request); - } - - public void sendSms(final NotificationRequest request) { - if (request.receiver().isSmsNotificationActivated()) { - rabbitTemplate.convertAndSend( - ExchangeName.NOTIFICATION.getName(), - RoutingKey.NOTIFICATION_SMS.getKey(), - request); - } - } - public void sendFcmWebPush(final NotificationRequest request) { - final Notification notification = notificationMapper.toNotification(request); - notificationRepository.save(notification); + @Override + public void publish(final NotificationRequest request) { rabbitTemplate.convertAndSend( ExchangeName.NOTIFICATION.getName(), RoutingKey.NOTIFICATION_FCM.getKey(), request); // final Long receiverId = request.receiver().getId(); diff --git a/src/main/java/com/amorgakco/backend/notification/infrastructure/publisher/Publisher.java b/src/main/java/com/amorgakco/backend/notification/infrastructure/publisher/Publisher.java new file mode 100644 index 0000000..5d04607 --- /dev/null +++ b/src/main/java/com/amorgakco/backend/notification/infrastructure/publisher/Publisher.java @@ -0,0 +1,7 @@ +package com.amorgakco.backend.notification.infrastructure.publisher; + +import com.amorgakco.backend.notification.infrastructure.consumer.NotificationRequest; + +public interface Publisher { + void publish(NotificationRequest request); +} diff --git a/src/main/java/com/amorgakco/backend/notification/infrastructure/publisher/SmsAndFcmPublisher.java b/src/main/java/com/amorgakco/backend/notification/infrastructure/publisher/SmsAndFcmPublisher.java new file mode 100644 index 0000000..e0ed7d6 --- /dev/null +++ b/src/main/java/com/amorgakco/backend/notification/infrastructure/publisher/SmsAndFcmPublisher.java @@ -0,0 +1,19 @@ +package com.amorgakco.backend.notification.infrastructure.publisher; + +import com.amorgakco.backend.notification.infrastructure.consumer.NotificationRequest; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; + +@Component +@RequiredArgsConstructor +public class SmsAndFcmPublisher implements Publisher { + + private final SmsPublisher smsPublisher; + private final FcmPublisher fcmPublisher; + + @Override + public void publish(final NotificationRequest request) { + smsPublisher.publish(request); + fcmPublisher.publish(request); + } +} diff --git a/src/main/java/com/amorgakco/backend/notification/infrastructure/publisher/SmsPublisher.java b/src/main/java/com/amorgakco/backend/notification/infrastructure/publisher/SmsPublisher.java new file mode 100644 index 0000000..9d059c5 --- /dev/null +++ b/src/main/java/com/amorgakco/backend/notification/infrastructure/publisher/SmsPublisher.java @@ -0,0 +1,26 @@ +package com.amorgakco.backend.notification.infrastructure.publisher; + + +import com.amorgakco.backend.global.rabbitmq.ExchangeName; +import com.amorgakco.backend.global.rabbitmq.RoutingKey; +import com.amorgakco.backend.notification.infrastructure.consumer.NotificationRequest; +import lombok.RequiredArgsConstructor; +import org.springframework.amqp.rabbit.core.RabbitTemplate; +import org.springframework.stereotype.Component; + +@Component +@RequiredArgsConstructor +public class SmsPublisher implements Publisher { + + private final RabbitTemplate rabbitTemplate; + + @Override + public void publish(final NotificationRequest request) { + if (request.receiver().isSmsNotificationActivated()) { + rabbitTemplate.convertAndSend( + ExchangeName.NOTIFICATION.getName(), + RoutingKey.NOTIFICATION_SMS.getKey(), + request); + } + } +} diff --git a/src/main/java/com/amorgakco/backend/notification/repository/NotificationRepository.java b/src/main/java/com/amorgakco/backend/notification/repository/NotificationRepository.java index a4264f2..40bb42c 100644 --- a/src/main/java/com/amorgakco/backend/notification/repository/NotificationRepository.java +++ b/src/main/java/com/amorgakco/backend/notification/repository/NotificationRepository.java @@ -1,7 +1,6 @@ package com.amorgakco.backend.notification.repository; import com.amorgakco.backend.notification.domain.Notification; - import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Slice; import org.springframework.data.jpa.repository.JpaRepository; @@ -12,6 +11,6 @@ public interface NotificationRepository extends JpaRepository { @Query( - "select n from Notification n join fetch n.receiver join fetch n.sender where n.receiver.id = :receiverId") + "select n from Notification n join fetch n.receiver where n.receiver.id = :receiverId") Slice findByReceiver(Long receiverId, Pageable pageable); } diff --git a/src/main/java/com/amorgakco/backend/notification/service/NotificationCreator.java b/src/main/java/com/amorgakco/backend/notification/service/NotificationCreator.java index c0b4501..0480ace 100644 --- a/src/main/java/com/amorgakco/backend/notification/service/NotificationCreator.java +++ b/src/main/java/com/amorgakco/backend/notification/service/NotificationCreator.java @@ -1,50 +1,67 @@ package com.amorgakco.backend.notification.service; import com.amorgakco.backend.member.domain.Member; -import com.amorgakco.backend.notification.domain.NotificationTitle; +import com.amorgakco.backend.notification.domain.NotificationType; +import com.amorgakco.backend.notification.domain.SendingType; import com.amorgakco.backend.notification.infrastructure.consumer.NotificationRequest; - import lombok.AccessLevel; import lombok.NoArgsConstructor; @NoArgsConstructor(access = AccessLevel.PRIVATE) public class NotificationCreator { - private static final String PARTICIPATION = "%s 님께서 모각코에 참여하길 원합니다."; - private static final String PARTICIPATION_APPROVE = "%s 님께서 %s 님의 모각코 참여를 허가했습니다."; - private static final String PARTICIPATION_REJECT = "%s 님께서 %s 님의 모각코 참여를 거절했습니다."; + public static NotificationRequest participationRequest( + final Member sender, final Member receiver, String groupName) { + return NotificationRequest.builder() + .receiver(receiver) + .sendingType(SendingType.SMS_AND_WEB_PUSH) + .title(NotificationType.PARTICIPATION_REQUEST.getTitle()) + .content(NotificationType.PARTICIPATION_REQUEST.getContent() + .formatted(sender.getNickname(), groupName)) + .build(); + } + + public static NotificationRequest participationApprove( + final Member receiver, final String groupName) { + return NotificationRequest.builder() + .receiver(receiver) + .sendingType(SendingType.WEB_PUSH) + .title(NotificationType.PARTICIPATION_APPROVED.getTitle()) + .content(NotificationType.PARTICIPATION_APPROVED.getContent() + .formatted(groupName)) + .build(); + } - public static NotificationRequest participationNotification( - final Member sender, final Member receiver) { + public static NotificationRequest participationReject( + final Member receiver, final String groupName) { return NotificationRequest.builder() - .sender(sender) .receiver(receiver) - .notificationTitle(NotificationTitle.PARTICIPATION_REQUEST) - .content(PARTICIPATION.formatted(sender.getNickname())) + .sendingType(SendingType.WEB_PUSH) + .title(NotificationType.PARTICIPATION_REJECTED.getTitle()) + .content(NotificationType.PARTICIPATION_REJECTED.getContent() + .formatted(groupName)) .build(); } - public static NotificationRequest participationApproveNotification( - final Member sender, final Member receiver) { + public static NotificationRequest tardy( + final Member sender, final Member receiver, final String groupName, final int requestMinute) { return NotificationRequest.builder() - .sender(sender) .receiver(receiver) - .notificationTitle(NotificationTitle.PARTICIPATION_APPROVED) - .content( - PARTICIPATION_APPROVE.formatted( - sender.getNickname(), receiver.getNickname())) + .sendingType(SendingType.WEB_PUSH) + .title(NotificationType.PARTICIPATION_TARDINESS.getTitle()) + .content(NotificationType.PARTICIPATION_TARDINESS.getContent() + .formatted(sender.getNickname(), groupName, requestMinute)) .build(); } - public static NotificationRequest participationRejectNotification( - final Member sender, final Member receiver) { + public static NotificationRequest withdraw( + final Member sender, final Member receiver, final String groupName) { return NotificationRequest.builder() - .sender(sender) .receiver(receiver) - .notificationTitle(NotificationTitle.PARTICIPATION_REJECTED) - .content( - PARTICIPATION_REJECT.formatted( - sender.getNickname(), receiver.getNickname())) + .sendingType(SendingType.WEB_PUSH) + .title(NotificationType.PARTICIPATION_TARDINESS.getTitle()) + .content(NotificationType.PARTICIPATION_TARDINESS.getContent() + .formatted(sender.getNickname(), groupName)) .build(); } } diff --git a/src/main/java/com/amorgakco/backend/notification/service/NotificationService.java b/src/main/java/com/amorgakco/backend/notification/service/NotificationService.java index ed3d10c..b17558f 100644 --- a/src/main/java/com/amorgakco/backend/notification/service/NotificationService.java +++ b/src/main/java/com/amorgakco/backend/notification/service/NotificationService.java @@ -4,9 +4,7 @@ import com.amorgakco.backend.notification.dto.NotificationMessageResponse; import com.amorgakco.backend.notification.repository.NotificationRepository; import com.amorgakco.backend.notification.service.mapper.NotificationMapper; - import lombok.RequiredArgsConstructor; - import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Slice; import org.springframework.data.domain.Sort; diff --git a/src/main/java/com/amorgakco/backend/notification/service/mapper/NotificationMapper.java b/src/main/java/com/amorgakco/backend/notification/service/mapper/NotificationMapper.java index 916c63c..80750e0 100644 --- a/src/main/java/com/amorgakco/backend/notification/service/mapper/NotificationMapper.java +++ b/src/main/java/com/amorgakco/backend/notification/service/mapper/NotificationMapper.java @@ -4,7 +4,6 @@ import com.amorgakco.backend.notification.dto.NotificationMessage; import com.amorgakco.backend.notification.dto.NotificationMessageResponse; import com.amorgakco.backend.notification.infrastructure.consumer.NotificationRequest; - import org.springframework.data.domain.Slice; import org.springframework.stereotype.Component; @@ -30,16 +29,16 @@ private List getNotificationMessages( private NotificationMessage toNotificationMessage(final Notification notification) { return NotificationMessage.builder() - .title(notification.getNotificationTitle().getTitle()) + .title(notification.getTitle()) .content(notification.getContent()) .build(); } public Notification toNotification(final NotificationRequest request) { return Notification.builder() + .title(request.title()) + .sendingType(request.sendingType()) .receiver(request.receiver()) - .sender(request.sender()) - .notificationTitle(request.notificationTitle()) .content(request.content()) .build(); } diff --git a/src/main/java/com/amorgakco/backend/oauth2/controller/Oauth2Controller.java b/src/main/java/com/amorgakco/backend/oauth2/controller/Oauth2Controller.java index c793411..acf9b24 100644 --- a/src/main/java/com/amorgakco/backend/oauth2/controller/Oauth2Controller.java +++ b/src/main/java/com/amorgakco/backend/oauth2/controller/Oauth2Controller.java @@ -7,11 +7,8 @@ import com.amorgakco.backend.oauth2.dto.Oauth2LoginResponse; import com.amorgakco.backend.oauth2.dto.Oauth2MemberResponse; import com.amorgakco.backend.oauth2.service.Oauth2Service; - import jakarta.servlet.http.HttpServletResponse; - import lombok.RequiredArgsConstructor; - import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; diff --git a/src/main/java/com/amorgakco/backend/oauth2/converter/Oauth2ProviderConverter.java b/src/main/java/com/amorgakco/backend/oauth2/converter/Oauth2ProviderConverter.java index b12ca7f..490e5aa 100644 --- a/src/main/java/com/amorgakco/backend/oauth2/converter/Oauth2ProviderConverter.java +++ b/src/main/java/com/amorgakco/backend/oauth2/converter/Oauth2ProviderConverter.java @@ -2,7 +2,6 @@ import com.amorgakco.backend.global.exception.InvalidOauth2ProviderException; import com.amorgakco.backend.member.domain.Oauth2ProviderType; - import org.springframework.core.convert.converter.Converter; import org.springframework.stereotype.Component; diff --git a/src/main/java/com/amorgakco/backend/oauth2/dto/Oauth2LoginResponse.java b/src/main/java/com/amorgakco/backend/oauth2/dto/Oauth2LoginResponse.java index 7ddbca1..a1502ac 100644 --- a/src/main/java/com/amorgakco/backend/oauth2/dto/Oauth2LoginResponse.java +++ b/src/main/java/com/amorgakco/backend/oauth2/dto/Oauth2LoginResponse.java @@ -3,4 +3,5 @@ import lombok.Builder; @Builder -public record Oauth2LoginResponse(Oauth2MemberResponse oauth2MemberResponse, String accessToken) {} +public record Oauth2LoginResponse(Oauth2MemberResponse oauth2MemberResponse, String accessToken) { +} diff --git a/src/main/java/com/amorgakco/backend/oauth2/dto/Oauth2MemberResponse.java b/src/main/java/com/amorgakco/backend/oauth2/dto/Oauth2MemberResponse.java index 435e919..cb95f82 100644 --- a/src/main/java/com/amorgakco/backend/oauth2/dto/Oauth2MemberResponse.java +++ b/src/main/java/com/amorgakco/backend/oauth2/dto/Oauth2MemberResponse.java @@ -3,4 +3,5 @@ import lombok.Builder; @Builder -public record Oauth2MemberResponse(String memberId, String nickname, String imgUrl) {} +public record Oauth2MemberResponse(String memberId, String nickname, String imgUrl) { +} diff --git a/src/main/java/com/amorgakco/backend/oauth2/provider/Oauth2Member.java b/src/main/java/com/amorgakco/backend/oauth2/provider/Oauth2Member.java index 343b10c..a21f682 100644 --- a/src/main/java/com/amorgakco/backend/oauth2/provider/Oauth2Member.java +++ b/src/main/java/com/amorgakco/backend/oauth2/provider/Oauth2Member.java @@ -1,9 +1,9 @@ package com.amorgakco.backend.oauth2.provider; import com.amorgakco.backend.member.domain.Oauth2ProviderType; - import lombok.Builder; @Builder public record Oauth2Member( - String oauth2Id, String imgUrl, String nickname, Oauth2ProviderType oauth2ProviderType) {} + String oauth2Id, String imgUrl, String nickname, Oauth2ProviderType oauth2ProviderType) { +} diff --git a/src/main/java/com/amorgakco/backend/oauth2/provider/Oauth2ProviderSelector.java b/src/main/java/com/amorgakco/backend/oauth2/provider/Oauth2ProviderSelector.java index d2f9245..4c1107b 100644 --- a/src/main/java/com/amorgakco/backend/oauth2/provider/Oauth2ProviderSelector.java +++ b/src/main/java/com/amorgakco/backend/oauth2/provider/Oauth2ProviderSelector.java @@ -2,7 +2,6 @@ import com.amorgakco.backend.global.exception.InvalidOauth2ProviderException; import com.amorgakco.backend.member.domain.Oauth2ProviderType; - import org.springframework.stereotype.Component; import java.util.Map; diff --git a/src/main/java/com/amorgakco/backend/oauth2/provider/kakao/KakaoAuthorization.java b/src/main/java/com/amorgakco/backend/oauth2/provider/kakao/KakaoAuthorization.java index bdad436..c873f3e 100644 --- a/src/main/java/com/amorgakco/backend/oauth2/provider/kakao/KakaoAuthorization.java +++ b/src/main/java/com/amorgakco/backend/oauth2/provider/kakao/KakaoAuthorization.java @@ -11,4 +11,5 @@ public record KakaoAuthorization( Integer expiresIn, String refreshToken, Integer refreshTokenExpiresIn, - String scope) {} + String scope) { +} diff --git a/src/main/java/com/amorgakco/backend/oauth2/provider/kakao/KakaoMemberResponse.java b/src/main/java/com/amorgakco/backend/oauth2/provider/kakao/KakaoMemberResponse.java index 227f9cc..0f78d97 100644 --- a/src/main/java/com/amorgakco/backend/oauth2/provider/kakao/KakaoMemberResponse.java +++ b/src/main/java/com/amorgakco/backend/oauth2/provider/kakao/KakaoMemberResponse.java @@ -17,8 +17,10 @@ public Oauth2Member toOauth2Member() { } @JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class) - public record KakaoAccount(Profile profile) {} + public record KakaoAccount(Profile profile) { + } @JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class) - public record Profile(String nickname, String profileImageUrl) {} + public record Profile(String nickname, String profileImageUrl) { + } } diff --git a/src/main/java/com/amorgakco/backend/oauth2/provider/kakao/KakaoOAuth2ProviderService.java b/src/main/java/com/amorgakco/backend/oauth2/provider/kakao/KakaoOAuth2ProviderService.java index c4e3d55..e116fdb 100644 --- a/src/main/java/com/amorgakco/backend/oauth2/provider/kakao/KakaoOAuth2ProviderService.java +++ b/src/main/java/com/amorgakco/backend/oauth2/provider/kakao/KakaoOAuth2ProviderService.java @@ -4,10 +4,8 @@ import com.amorgakco.backend.member.domain.Oauth2ProviderType; import com.amorgakco.backend.oauth2.provider.Oauth2Member; import com.amorgakco.backend.oauth2.provider.Oauth2ProviderService; - import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; - import org.springframework.stereotype.Service; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; diff --git a/src/main/java/com/amorgakco/backend/oauth2/provider/kakao/KakaoOauth2Properties.java b/src/main/java/com/amorgakco/backend/oauth2/provider/kakao/KakaoOauth2Properties.java index 6fff1d5..24c6d3c 100644 --- a/src/main/java/com/amorgakco/backend/oauth2/provider/kakao/KakaoOauth2Properties.java +++ b/src/main/java/com/amorgakco/backend/oauth2/provider/kakao/KakaoOauth2Properties.java @@ -8,4 +8,5 @@ public record KakaoOauth2Properties( String redirectUri, String clientId, String clientSecret, - String[] scope) {} + String[] scope) { +} diff --git a/src/main/java/com/amorgakco/backend/oauth2/service/Oauth2Service.java b/src/main/java/com/amorgakco/backend/oauth2/service/Oauth2Service.java index 9b08a74..402c6cb 100644 --- a/src/main/java/com/amorgakco/backend/oauth2/service/Oauth2Service.java +++ b/src/main/java/com/amorgakco/backend/oauth2/service/Oauth2Service.java @@ -6,9 +6,7 @@ import com.amorgakco.backend.oauth2.provider.Oauth2Member; import com.amorgakco.backend.oauth2.provider.Oauth2ProviderSelector; import com.amorgakco.backend.oauth2.provider.Oauth2ProviderService; - import lombok.RequiredArgsConstructor; - import org.springframework.stereotype.Service; @Service diff --git a/src/main/java/com/amorgakco/backend/participant/controller/ParticipantController.java b/src/main/java/com/amorgakco/backend/participant/controller/ParticipantController.java index 0d9aa78..fa95431 100644 --- a/src/main/java/com/amorgakco/backend/participant/controller/ParticipantController.java +++ b/src/main/java/com/amorgakco/backend/participant/controller/ParticipantController.java @@ -3,13 +3,16 @@ import com.amorgakco.backend.global.argumentresolver.AuthMemberId; import com.amorgakco.backend.group.dto.LocationVerificationRequest; import com.amorgakco.backend.participant.dto.ParticipationHistoryResponse; +import com.amorgakco.backend.participant.dto.TardinessRequest; import com.amorgakco.backend.participant.service.ParticipantService; - +import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; - import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PatchMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; @@ -36,4 +39,35 @@ public ParticipationHistoryResponse getParticipationHistory( @RequestParam final Integer page, @AuthMemberId final Long memberId) { return participantService.getParticipationHistory(memberId, page); } + + @DeleteMapping("/groups/{groupId}") + public void withdraw(@PathVariable final Long groupId, @AuthMemberId final Long memberId) { + participantService.withdraw(groupId, memberId); + } + + @PostMapping("/groups/{groupId}/tardiness") + public void tardy( + @PathVariable final Long groupId, + @AuthMemberId final Long memberId, + @RequestBody @Valid final TardinessRequest tardinessRequest) { + participantService.tardy(groupId, memberId, tardinessRequest); + } + + @PatchMapping("/{targetMemberId}/groups/{groupId}/temperature-up") + public Integer upTemperature( + @PathVariable final Long targetMemberId, + @PathVariable final Long groupId, + @AuthMemberId final Long requestMemberId + ) { + return participantService.upTemperature(groupId, requestMemberId, targetMemberId); + } + + @PatchMapping("/{targetMemberId}/groups/{groupId}/temperature-down") + public Integer downTemperature( + @PathVariable final Long targetMemberId, + @PathVariable final Long groupId, + @AuthMemberId final Long requestMemberId + ) { + return participantService.downTemperature(groupId, requestMemberId, targetMemberId); + } } diff --git a/src/main/java/com/amorgakco/backend/participant/domain/Participant.java b/src/main/java/com/amorgakco/backend/participant/domain/Participant.java index 2efbb13..8a70a31 100644 --- a/src/main/java/com/amorgakco/backend/participant/domain/Participant.java +++ b/src/main/java/com/amorgakco/backend/participant/domain/Participant.java @@ -4,9 +4,14 @@ import com.amorgakco.backend.global.exception.IllegalAccessException; import com.amorgakco.backend.group.domain.Group; import com.amorgakco.backend.member.domain.Member; - -import jakarta.persistence.*; - +import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; import lombok.AccessLevel; import lombok.Getter; import lombok.NoArgsConstructor; @@ -18,7 +23,9 @@ @NoArgsConstructor(access = AccessLevel.PROTECTED) public class Participant extends BaseTime { - @Id @GeneratedValue private Long id; + @Id + @GeneratedValue + private Long id; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn @@ -36,6 +43,19 @@ public Participant(final Member member) { this.locationVerificationStatus = LocationVerificationStatus.UNVERIFIED; } + @Override + public boolean equals(final Object o) { + if (this==o) return true; + if (o==null || getClass()!=o.getClass()) return false; + final Participant that = (Participant) o; + return Objects.equals(getMember().getId(), that.getMember().getId()); + } + + @Override + public int hashCode() { + return Objects.hash(getMember().getId()); + } + public void verify(final double longitude, final double latitude) { if (isVerified()) { throw IllegalAccessException.verificationDuplicated(); @@ -52,16 +72,19 @@ public void add(final Group group) { this.group = group; } - @Override - public boolean equals(final Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - final Participant that = (Participant) o; - return Objects.equals(getMember().getId(), that.getMember().getId()); + public Integer upTemperature(final Participant requestParticipant) { + requestParticipant.validateSameGroupParticipant(this); + return member.upMoGakCoTemperature(); } - @Override - public int hashCode() { - return Objects.hash(getMember().getId()); + private void validateSameGroupParticipant(final Participant targetParticipant) { + if (!Objects.equals(this.group.getId(), targetParticipant.getGroup().getId())) { + throw IllegalAccessException.notSameGroupParticipant(); + } + } + + public Integer downTemperature(final Participant requestParticipant) { + requestParticipant.validateSameGroupParticipant(this); + return member.downMoGakCoTemperature(); } } diff --git a/src/main/java/com/amorgakco/backend/participant/dto/ParticipationHistory.java b/src/main/java/com/amorgakco/backend/participant/dto/ParticipationHistory.java index 719b8ad..85aa836 100644 --- a/src/main/java/com/amorgakco/backend/participant/dto/ParticipationHistory.java +++ b/src/main/java/com/amorgakco/backend/participant/dto/ParticipationHistory.java @@ -6,4 +6,5 @@ @Builder public record ParticipationHistory( - Long groupId, String name, String address, LocalDateTime beginAt, LocalDateTime endAt) {} + Long groupId, String name, String address, LocalDateTime beginAt, LocalDateTime endAt) { +} diff --git a/src/main/java/com/amorgakco/backend/participant/dto/ParticipationHistoryResponse.java b/src/main/java/com/amorgakco/backend/participant/dto/ParticipationHistoryResponse.java index 168f675..77a4488 100644 --- a/src/main/java/com/amorgakco/backend/participant/dto/ParticipationHistoryResponse.java +++ b/src/main/java/com/amorgakco/backend/participant/dto/ParticipationHistoryResponse.java @@ -10,4 +10,5 @@ public record ParticipationHistoryResponse( int elementSize, boolean hasNext, List activatedGroup, - List InactivatedGroup) {} + List InactivatedGroup) { +} diff --git a/src/main/java/com/amorgakco/backend/participant/dto/TardinessRequest.java b/src/main/java/com/amorgakco/backend/participant/dto/TardinessRequest.java new file mode 100644 index 0000000..a799e67 --- /dev/null +++ b/src/main/java/com/amorgakco/backend/participant/dto/TardinessRequest.java @@ -0,0 +1,7 @@ +package com.amorgakco.backend.participant.dto; + +import org.hibernate.validator.constraints.Range; + +public record TardinessRequest( + @Range(min = 5, max = 60, message = "5분 이상 60분 이하만 입력해주세요.") Integer minute) { +} diff --git a/src/main/java/com/amorgakco/backend/participant/repository/ParticipantRepository.java b/src/main/java/com/amorgakco/backend/participant/repository/ParticipantRepository.java index d577de7..6ff2dcf 100644 --- a/src/main/java/com/amorgakco/backend/participant/repository/ParticipantRepository.java +++ b/src/main/java/com/amorgakco/backend/participant/repository/ParticipantRepository.java @@ -1,10 +1,11 @@ package com.amorgakco.backend.participant.repository; import com.amorgakco.backend.participant.domain.Participant; - +import jakarta.persistence.LockModeType; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Slice; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Lock; import org.springframework.data.jpa.repository.Query; import org.springframework.stereotype.Repository; @@ -16,6 +17,7 @@ public interface ParticipantRepository extends JpaRepository @Query("select p from Participant p join fetch p.group where p.member.id = :memberId") Slice findByMember(Long memberId, Pageable pageable); + @Lock(LockModeType.PESSIMISTIC_WRITE) @Query( "select p from Participant p join fetch p.group where p.group.id = :groupId and p.member.id = :memberId") Optional findByGroupAndMember(final Long groupId, final Long memberId); diff --git a/src/main/java/com/amorgakco/backend/participant/service/ParticipantService.java b/src/main/java/com/amorgakco/backend/participant/service/ParticipantService.java index afeac6a..ebb8f61 100644 --- a/src/main/java/com/amorgakco/backend/participant/service/ParticipantService.java +++ b/src/main/java/com/amorgakco/backend/participant/service/ParticipantService.java @@ -1,14 +1,18 @@ package com.amorgakco.backend.participant.service; +import com.amorgakco.backend.global.config.redisson.Lock; import com.amorgakco.backend.global.exception.ResourceNotFoundException; +import com.amorgakco.backend.group.domain.Group; import com.amorgakco.backend.group.dto.LocationVerificationRequest; +import com.amorgakco.backend.group.service.GroupService; +import com.amorgakco.backend.notification.infrastructure.NotificationPublisherFacade; +import com.amorgakco.backend.notification.service.NotificationCreator; import com.amorgakco.backend.participant.domain.Participant; import com.amorgakco.backend.participant.dto.ParticipationHistoryResponse; +import com.amorgakco.backend.participant.dto.TardinessRequest; import com.amorgakco.backend.participant.repository.ParticipantRepository; import com.amorgakco.backend.participant.service.mapper.ParticipantMapper; - import lombok.RequiredArgsConstructor; - import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Slice; import org.springframework.data.domain.Sort; @@ -17,23 +21,28 @@ @Service @RequiredArgsConstructor -@Transactional(readOnly = true) public class ParticipantService { private static final Integer PAGE_SIZE = 10; private final ParticipantRepository participantRepository; private final ParticipantMapper participantMapper; + private final GroupService groupService; + private final NotificationPublisherFacade notificationPublisherFacade; @Transactional public void verifyParticipantLocation( final LocationVerificationRequest request, final Long memberId) { - final Participant participant = - participantRepository - .findByGroupAndMember(request.groupId(), memberId) - .orElseThrow(ResourceNotFoundException::participantsNotFound); + final Participant participant = getParticipant(request.groupId(), memberId); participant.verify(request.longitude(), request.latitude()); } + public Participant getParticipant(final Long groupId, final Long memberId) { + return participantRepository + .findByGroupAndMember(groupId, memberId) + .orElseThrow(ResourceNotFoundException::participantsNotFound); + } + + @Transactional(readOnly = true) public ParticipationHistoryResponse getParticipationHistory( final Long memberId, final Integer page) { final PageRequest pageRequest = @@ -42,4 +51,42 @@ public ParticipationHistoryResponse getParticipationHistory( participantRepository.findByMember(memberId, pageRequest); return participantMapper.toParticipationHistoryResponse(participantSlice); } + + @Transactional + public void withdraw(final Long groupId, final Long memberId) { + final Participant participant = getParticipant(groupId, memberId); + participantRepository.delete(participant); + final Group group = groupService.getGroup(groupId); + notificationPublisherFacade.send(NotificationCreator.withdraw( + participant.getMember(), + group.getHost(), + group.getName() + )); + } + + @Transactional + public void tardy(final Long groupId, final Long memberId, final TardinessRequest tardinessRequest) { + final Participant participant = getParticipant(groupId, memberId); + final Group group = groupService.getGroup(groupId); + notificationPublisherFacade.send(NotificationCreator.tardy( + participant.getMember(), + group.getHost(), + group.getName(), + tardinessRequest.minute() + )); + } + + @Lock(key = "#targetMemberId") + public Integer upTemperature(final Long groupId, final Long requestMemberId, final Long targetMemberId) { + final Participant requestParticipant = getParticipant(groupId, requestMemberId); + final Participant targetParticipant = getParticipant(groupId, targetMemberId); + return targetParticipant.upTemperature(requestParticipant); + } + + @Lock(key = "#targetMemberId") + public Integer downTemperature(final Long groupId, final Long requestMemberId, final Long targetMemberId) { + final Participant requestParticipant = getParticipant(groupId, requestMemberId); + final Participant targetParticipant = getParticipant(groupId, targetMemberId); + return targetParticipant.downTemperature(requestParticipant); + } } diff --git a/src/main/java/com/amorgakco/backend/participant/service/mapper/ParticipantMapper.java b/src/main/java/com/amorgakco/backend/participant/service/mapper/ParticipantMapper.java index 16c8492..b158289 100644 --- a/src/main/java/com/amorgakco/backend/participant/service/mapper/ParticipantMapper.java +++ b/src/main/java/com/amorgakco/backend/participant/service/mapper/ParticipantMapper.java @@ -4,7 +4,6 @@ import com.amorgakco.backend.participant.domain.Participant; import com.amorgakco.backend.participant.dto.ParticipationHistory; import com.amorgakco.backend.participant.dto.ParticipationHistoryResponse; - import org.springframework.data.domain.Slice; import org.springframework.stereotype.Component; diff --git a/src/test/java/com/amorgakco/backend/fixture/group/TestGroupFactory.java b/src/test/java/com/amorgakco/backend/fixture/group/TestGroupFactory.java index 903c88f..8b5faf7 100644 --- a/src/test/java/com/amorgakco/backend/fixture/group/TestGroupFactory.java +++ b/src/test/java/com/amorgakco/backend/fixture/group/TestGroupFactory.java @@ -18,7 +18,7 @@ public class TestGroupFactory { private static final double LONGITUDE = 126.9748397; private static final double LATITUDE = 37.5703901; - private static final int GROUP_CAPACITY = 3; + private static final int GROUP_CAPACITY = 4; private static final String ADDRESS = "서울특별시 종로구 신문로1가 23"; private static final String DESCRIPTION = "모각코 합시다."; private static final String NAME = "AmorGakCo"; @@ -121,6 +121,7 @@ public static GroupSearchRequest cityLevelGroupSearchRequest() { 37.554498367410076, 126.97758064203596); } + ; public static GroupSearchRequest dongLevelGroupSearchRequest() { @@ -132,6 +133,7 @@ public static GroupSearchRequest dongLevelGroupSearchRequest() { 37.56826582236329, 126.97879899797212); } + ; public static GroupSearchRequest guLevelGroupSearchRequest() { @@ -143,5 +145,6 @@ public static GroupSearchRequest guLevelGroupSearchRequest() { 37.56826582236329, 126.97879899797212); } + ; } diff --git a/src/test/java/com/amorgakco/backend/fixture/notification/TestNotificationFactory.java b/src/test/java/com/amorgakco/backend/fixture/notification/TestNotificationFactory.java index 97b581e..f15a885 100644 --- a/src/test/java/com/amorgakco/backend/fixture/notification/TestNotificationFactory.java +++ b/src/test/java/com/amorgakco/backend/fixture/notification/TestNotificationFactory.java @@ -26,10 +26,10 @@ private static NotificationMessage notificationMessage() { final Member sender = TestMemberFactory.create(1L); final Member receiver = TestMemberFactory.create(2L); final NotificationRequest request = - NotificationCreator.participationNotification(sender, receiver); + NotificationCreator.participationRequest(sender, receiver, "mogakco"); return NotificationMessage.builder() .content(request.content()) - .title(request.notificationTitle().getTitle()) + .title(request.title()) .build(); } } diff --git a/src/test/java/com/amorgakco/backend/group/domain/GroupTest.java b/src/test/java/com/amorgakco/backend/group/domain/GroupTest.java index dcbfca5..6bc5b4b 100644 --- a/src/test/java/com/amorgakco/backend/group/domain/GroupTest.java +++ b/src/test/java/com/amorgakco/backend/group/domain/GroupTest.java @@ -1,7 +1,5 @@ package com.amorgakco.backend.group.domain; -import static org.assertj.core.api.Assertions.*; - import com.amorgakco.backend.fixture.group.TestGroupFactory; import com.amorgakco.backend.fixture.group.TestParticipantsFactory; import com.amorgakco.backend.fixture.member.TestMemberFactory; @@ -9,10 +7,12 @@ import com.amorgakco.backend.global.exception.IllegalAccessException; import com.amorgakco.backend.member.domain.Member; import com.amorgakco.backend.participant.domain.Participant; - import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + class GroupTest { @Test @@ -22,12 +22,13 @@ void getCurrentGroupSize() { final Member host = TestMemberFactory.create(1L); final Group group = TestGroupFactory.create(host); final Member member = TestMemberFactory.create(2L); + final int expectGroupSize = 2; final Participant participant = TestParticipantsFactory.create(member); group.addParticipants(participant); // when final int currentGroupSize = group.getCurrentGroupSize(); // then - assertThat(currentGroupSize).isEqualTo(2); + assertThat(currentGroupSize).isEqualTo(expectGroupSize); } @Test diff --git a/src/test/java/com/amorgakco/backend/groupparticipation/controller/GroupParticipationControllerTest.java b/src/test/java/com/amorgakco/backend/groupparticipation/controller/GroupParticipationControllerTest.java index 2ce8996..5c401cc 100644 --- a/src/test/java/com/amorgakco/backend/groupparticipation/controller/GroupParticipationControllerTest.java +++ b/src/test/java/com/amorgakco/backend/groupparticipation/controller/GroupParticipationControllerTest.java @@ -1,8 +1,16 @@ package com.amorgakco.backend.groupparticipation.controller; +import com.amorgakco.backend.docs.RestDocsTest; +import com.amorgakco.backend.groupparticipation.service.GroupParticipationService; +import com.amorgakco.backend.security.WithMockMember; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.web.servlet.ResultActions; + import static com.amorgakco.backend.docs.ApiDocsUtils.getDocumentRequest; import static com.amorgakco.backend.docs.ApiDocsUtils.getDocumentResponse; - import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.patch; import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.post; @@ -11,20 +19,11 @@ import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -import com.amorgakco.backend.docs.RestDocsTest; -import com.amorgakco.backend.groupparticipation.service.GroupParticipationService; -import com.amorgakco.backend.security.WithMockMember; - -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.test.web.servlet.ResultActions; - @WebMvcTest(GroupParticipationController.class) class GroupParticipationControllerTest extends RestDocsTest { - @MockBean private GroupParticipationService groupParticipationService; + @MockBean + private GroupParticipationService groupParticipationService; @Test @DisplayName("그룹에 참여요청을 보낼 수 있다.") diff --git a/src/test/java/com/amorgakco/backend/groupparticipation/domain/GroupParticipationTest.java b/src/test/java/com/amorgakco/backend/groupparticipation/domain/GroupParticipationTest.java index a65e117..f76d0d9 100644 --- a/src/test/java/com/amorgakco/backend/groupparticipation/domain/GroupParticipationTest.java +++ b/src/test/java/com/amorgakco/backend/groupparticipation/domain/GroupParticipationTest.java @@ -1,14 +1,13 @@ package com.amorgakco.backend.groupparticipation.domain; -import static org.assertj.core.api.Assertions.*; - import com.amorgakco.backend.fixture.groupparticipation.TestGroupParticipationFactory; import com.amorgakco.backend.fixture.member.TestMemberFactory; import com.amorgakco.backend.member.domain.Member; - import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import static org.assertj.core.api.Assertions.assertThat; + class GroupParticipationTest { @Test diff --git a/src/test/java/com/amorgakco/backend/participant/service/ParticipantServiceTest.java b/src/test/java/com/amorgakco/backend/participant/service/ParticipantServiceTest.java new file mode 100644 index 0000000..681c1fe --- /dev/null +++ b/src/test/java/com/amorgakco/backend/participant/service/ParticipantServiceTest.java @@ -0,0 +1,67 @@ +package com.amorgakco.backend.participant.service; + +import com.amorgakco.backend.fixture.group.TestGroupFactory; +import com.amorgakco.backend.group.domain.Group; +import com.amorgakco.backend.group.repository.GroupRepository; +import com.amorgakco.backend.member.domain.Member; +import com.amorgakco.backend.member.repository.MemberRepository; +import com.amorgakco.backend.participant.domain.Participant; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.atomic.AtomicInteger; + +@SpringBootTest +class ParticipantServiceTest { + + @Autowired + private ParticipantService participantService; + @Autowired + private MemberRepository memberRepository; + @Autowired + private GroupRepository groupRepository; + + + @Test + void multithreadTest() throws InterruptedException { + Member member1 = memberRepository.save(Member.builder().nickname("member1").build()); + Member member2 = memberRepository.save(Member.builder().nickname("member2").build()); + Group group = TestGroupFactory.create(member1); + group.addParticipants(new Participant(member2)); + groupRepository.saveAndFlush(group); + + int memberCount = 20; + + ExecutorService executorService = Executors.newFixedThreadPool(memberCount); + CountDownLatch latch = new CountDownLatch(memberCount); + AtomicInteger successCount = new AtomicInteger(); + AtomicInteger failCount = new AtomicInteger(); + + for (int i = 0; i < memberCount; i++) { + executorService.execute(() -> { + try { + participantService.upTemperature(1L, 1L, 2L); + successCount.incrementAndGet(); + } catch (Exception e) { + System.out.println("e.getMessage() = " + e.getMessage()); + failCount.incrementAndGet(); + } finally { + latch.countDown(); + } + }); + } + + latch.await(); + System.out.println("failCount = " + failCount); + System.out.println("successCount = " + successCount); + + Member member = memberRepository.findById(2L).get(); + Integer moGakCoTemperature = member.getMoGakCoTemperature(); + Assertions.assertThat(moGakCoTemperature).isEqualTo(memberCount); + } +} \ No newline at end of file diff --git a/src/test/resources/application-test.yml b/src/test/resources/application-test.yml new file mode 100644 index 0000000..e7967fc --- /dev/null +++ b/src/test/resources/application-test.yml @@ -0,0 +1,29 @@ +spring: + config: + activate: + on-profile: test + datasource: + driver-class-name: com.mysql.cj.jdbc.Driver + url: jdbc:mysql://localhost:3306/amorgakco + username: root + password: 1234 + jpa: + show-sql: true + hibernate: + ddl-auto: create + properties: + format_sql: true + hibernate: + dialect: org.hibernate.dialect.MySQLDialect + defer-datasource-initialization: true + data: + redis: + host: localhost + port: 6379 + rabbitmq: + host: localhost + port: 5672 + username: "guest" + password: "guest" + +fcm-secret-path: fcm-secret.json \ No newline at end of file From d65d601090dfea115ed4b282fc4d00dcd1057f39 Mon Sep 17 00:00:00 2001 From: songhaechan Date: Sun, 22 Sep 2024 02:47:10 +0900 Subject: [PATCH 02/22] hotfix:recover --- build.gradle | 3 +++ .../global/config/redisson/LockAop.java | 2 +- .../service/ParticipantServiceTest.java | 2 +- src/test/resources/application.yml | 20 +++++++------------ 4 files changed, 12 insertions(+), 15 deletions(-) diff --git a/build.gradle b/build.gradle index 0e189dc..4d834bd 100644 --- a/build.gradle +++ b/build.gradle @@ -53,6 +53,9 @@ dependencies { implementation 'org.springframework.boot:spring-boot-starter-amqp' implementation 'com.google.firebase:firebase-admin:9.3.0' implementation 'com.google.geometry:s2-geometry:2.0.0' + implementation group: 'org.springframework.boot', name: 'spring-boot-starter-validation' + runtimeOnly 'com.h2database:h2' + implementation 'org.redisson:redisson-spring-boot-starter:3.18.0' } tasks.named('test') { diff --git a/src/main/java/com/amorgakco/backend/global/config/redisson/LockAop.java b/src/main/java/com/amorgakco/backend/global/config/redisson/LockAop.java index 781e762..ee2654b 100644 --- a/src/main/java/com/amorgakco/backend/global/config/redisson/LockAop.java +++ b/src/main/java/com/amorgakco/backend/global/config/redisson/LockAop.java @@ -33,7 +33,7 @@ public Object lock(final ProceedingJoinPoint joinPoint) throws Throwable { RLock rLock = redissonClient.getLock(key); try { - boolean available = rLock.tryLock(lock.waitTime(), lock.leaseTime(), lock.timeUnit()); // (2) + boolean available = rLock.tryLock(lock.waitTime(), lock.leaseTime(), lock.timeUnit()); if (!available) { return false; } diff --git a/src/test/java/com/amorgakco/backend/participant/service/ParticipantServiceTest.java b/src/test/java/com/amorgakco/backend/participant/service/ParticipantServiceTest.java index 681c1fe..8a1e72e 100644 --- a/src/test/java/com/amorgakco/backend/participant/service/ParticipantServiceTest.java +++ b/src/test/java/com/amorgakco/backend/participant/service/ParticipantServiceTest.java @@ -48,7 +48,6 @@ void multithreadTest() throws InterruptedException { participantService.upTemperature(1L, 1L, 2L); successCount.incrementAndGet(); } catch (Exception e) { - System.out.println("e.getMessage() = " + e.getMessage()); failCount.incrementAndGet(); } finally { latch.countDown(); @@ -62,6 +61,7 @@ void multithreadTest() throws InterruptedException { Member member = memberRepository.findById(2L).get(); Integer moGakCoTemperature = member.getMoGakCoTemperature(); + System.out.println("moGakCoTemperature = " + moGakCoTemperature); Assertions.assertThat(moGakCoTemperature).isEqualTo(memberCount); } } \ No newline at end of file diff --git a/src/test/resources/application.yml b/src/test/resources/application.yml index d60a7e2..a06e39f 100644 --- a/src/test/resources/application.yml +++ b/src/test/resources/application.yml @@ -1,14 +1,8 @@ +server: + port: 8080 + spring: - datasource: - driver-class-name: com.mysql.cj.jdbc.Driver - url: jdbc:mysql://localhost:3306/amorgakco - username: root - password: 1234 - jpa: - show-sql: true - hibernate: - ddl-auto: none - properties: - hibernate: - format_sql: true - defer-datasource-initialization: true \ No newline at end of file + profiles: + active: test + group: + test: test,oauth2,jwt,notification \ No newline at end of file From 28f14d21b6109aea881335a863df485c57809391 Mon Sep 17 00:00:00 2001 From: songhaechan Date: Sun, 22 Sep 2024 03:01:06 +0900 Subject: [PATCH 03/22] =?UTF-8?q?test:=20=EB=AA=A8=EA=B0=81=EC=BD=94?= =?UTF-8?q?=EC=98=A8=EB=8F=84=20=EB=8F=99=EC=8B=9C=EC=84=B1=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/amorgakco/backend/group/domain/Group.java | 2 +- .../backend/participant/service/ParticipantServiceTest.java | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/amorgakco/backend/group/domain/Group.java b/src/main/java/com/amorgakco/backend/group/domain/Group.java index e419573..2215689 100644 --- a/src/main/java/com/amorgakco/backend/group/domain/Group.java +++ b/src/main/java/com/amorgakco/backend/group/domain/Group.java @@ -68,7 +68,7 @@ public Group( this.groupCapacity = groupCapacity; this.duration = new Duration(beginAt, endAt); this.location = new Location(longitude, latitude); - this.participants.add(new Participant(host)); + addParticipants(new Participant(host)); this.host = host; this.address = address; } diff --git a/src/test/java/com/amorgakco/backend/participant/service/ParticipantServiceTest.java b/src/test/java/com/amorgakco/backend/participant/service/ParticipantServiceTest.java index 8a1e72e..8aeebaa 100644 --- a/src/test/java/com/amorgakco/backend/participant/service/ParticipantServiceTest.java +++ b/src/test/java/com/amorgakco/backend/participant/service/ParticipantServiceTest.java @@ -7,6 +7,7 @@ import com.amorgakco.backend.member.repository.MemberRepository; import com.amorgakco.backend.participant.domain.Participant; import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; @@ -28,7 +29,8 @@ class ParticipantServiceTest { @Test - void multithreadTest() throws InterruptedException { + @DisplayName("멀티 스레드 환경에서 온도를 상승시킨 횟수 만큼 온도가 상승돼야한다.") + void moGakCoTemperatureConcurrencyTest() throws InterruptedException { Member member1 = memberRepository.save(Member.builder().nickname("member1").build()); Member member2 = memberRepository.save(Member.builder().nickname("member2").build()); Group group = TestGroupFactory.create(member1); From f7fd8cdcbae1eae4995a9d475f8229d73fa9cea8 Mon Sep 17 00:00:00 2001 From: songhaechan Date: Sun, 22 Sep 2024 16:34:10 +0900 Subject: [PATCH 04/22] =?UTF-8?q?setting:=20ci=20redis=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/amorgakco-ci.yml | 4 ++++ .../java/com/amorgakco/backend/group/domain/Group.java | 3 ++- .../groupparticipation/domain/GroupParticipation.java | 3 ++- .../java/com/amorgakco/backend/member/domain/Member.java | 3 ++- .../backend/notification/domain/Notification.java | 3 ++- .../backend/participant/domain/Participant.java | 3 ++- src/test/resources/application-test.yml | 9 +++++---- 7 files changed, 19 insertions(+), 9 deletions(-) diff --git a/.github/workflows/amorgakco-ci.yml b/.github/workflows/amorgakco-ci.yml index 927dc7d..959bf7d 100644 --- a/.github/workflows/amorgakco-ci.yml +++ b/.github/workflows/amorgakco-ci.yml @@ -10,6 +10,10 @@ jobs: build: runs-on: ubuntu-latest steps: + - name: Start Redis + uses: supercharge/redis-github-action@1.1.0 + with: + redis-version: 6 - uses: actions/checkout@v3 - uses: actions/setup-java@v3 with: diff --git a/src/main/java/com/amorgakco/backend/group/domain/Group.java b/src/main/java/com/amorgakco/backend/group/domain/Group.java index 2215689..421a8ff 100644 --- a/src/main/java/com/amorgakco/backend/group/domain/Group.java +++ b/src/main/java/com/amorgakco/backend/group/domain/Group.java @@ -11,6 +11,7 @@ import jakarta.persistence.Entity; import jakarta.persistence.FetchType; import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; import jakarta.persistence.Id; import jakarta.persistence.Index; import jakarta.persistence.ManyToOne; @@ -37,7 +38,7 @@ public class Group extends BaseTime { private final Set participants = new HashSet<>(); @Id - @GeneratedValue + @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; private String description; diff --git a/src/main/java/com/amorgakco/backend/groupparticipation/domain/GroupParticipation.java b/src/main/java/com/amorgakco/backend/groupparticipation/domain/GroupParticipation.java index 1d986c6..b11a786 100644 --- a/src/main/java/com/amorgakco/backend/groupparticipation/domain/GroupParticipation.java +++ b/src/main/java/com/amorgakco/backend/groupparticipation/domain/GroupParticipation.java @@ -10,6 +10,7 @@ import jakarta.persistence.Enumerated; import jakarta.persistence.FetchType; import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; import jakarta.persistence.Id; import jakarta.persistence.JoinColumn; import jakarta.persistence.ManyToOne; @@ -24,7 +25,7 @@ public class GroupParticipation extends BaseTime { @Id - @GeneratedValue + @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @ManyToOne(fetch = FetchType.LAZY) diff --git a/src/main/java/com/amorgakco/backend/member/domain/Member.java b/src/main/java/com/amorgakco/backend/member/domain/Member.java index 8666ed1..9a020aa 100644 --- a/src/main/java/com/amorgakco/backend/member/domain/Member.java +++ b/src/main/java/com/amorgakco/backend/member/domain/Member.java @@ -9,6 +9,7 @@ import jakarta.persistence.Enumerated; import jakarta.persistence.FetchType; import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; import jakarta.persistence.Id; import jakarta.persistence.JoinColumn; import jakarta.persistence.OneToMany; @@ -30,7 +31,7 @@ public class Member extends BaseTime { private static final Integer MIN_MOGAKCO_TEMPERATURE = -100; @Id - @GeneratedValue + @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Enumerated(EnumType.STRING) diff --git a/src/main/java/com/amorgakco/backend/notification/domain/Notification.java b/src/main/java/com/amorgakco/backend/notification/domain/Notification.java index c72a9b2..f2f3745 100644 --- a/src/main/java/com/amorgakco/backend/notification/domain/Notification.java +++ b/src/main/java/com/amorgakco/backend/notification/domain/Notification.java @@ -7,6 +7,7 @@ import jakarta.persistence.Enumerated; import jakarta.persistence.FetchType; import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; import jakarta.persistence.Id; import jakarta.persistence.ManyToOne; import lombok.AccessLevel; @@ -20,7 +21,7 @@ public class Notification extends BaseTime { @Id - @GeneratedValue + @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String title; diff --git a/src/main/java/com/amorgakco/backend/participant/domain/Participant.java b/src/main/java/com/amorgakco/backend/participant/domain/Participant.java index 8a70a31..c9397da 100644 --- a/src/main/java/com/amorgakco/backend/participant/domain/Participant.java +++ b/src/main/java/com/amorgakco/backend/participant/domain/Participant.java @@ -9,6 +9,7 @@ import jakarta.persistence.Enumerated; import jakarta.persistence.FetchType; import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; import jakarta.persistence.Id; import jakarta.persistence.JoinColumn; import jakarta.persistence.ManyToOne; @@ -24,7 +25,7 @@ public class Participant extends BaseTime { @Id - @GeneratedValue + @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @ManyToOne(fetch = FetchType.LAZY) diff --git a/src/test/resources/application-test.yml b/src/test/resources/application-test.yml index e7967fc..7f3833a 100644 --- a/src/test/resources/application-test.yml +++ b/src/test/resources/application-test.yml @@ -3,10 +3,11 @@ spring: activate: on-profile: test datasource: - driver-class-name: com.mysql.cj.jdbc.Driver - url: jdbc:mysql://localhost:3306/amorgakco - username: root - password: 1234 + driver-class-name: org.h2.Driver + url: + jdbc:h2:mem:amorgakco;MODE=MySQL; + username: sa + password: jpa: show-sql: true hibernate: From ac6de8351c4dbf864b9eb6e64fb1477ff6ba9d92 Mon Sep 17 00:00:00 2001 From: songhaechan Date: Sun, 22 Sep 2024 16:39:00 +0900 Subject: [PATCH 05/22] =?UTF-8?q?fix:=20rabbitmq=20test=20=EC=A0=9C?= =?UTF-8?q?=EC=99=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/index.html | 50 +++++++++---------- .../backend/global/config/RabbitMQConfig.java | 3 +- src/main/resources/static/docs/index.html | 50 +++++++++---------- 3 files changed, 52 insertions(+), 51 deletions(-) diff --git a/docs/index.html b/docs/index.html index 23318fa..37f5c03 100644 --- a/docs/index.html +++ b/docs/index.html @@ -522,9 +522,9 @@

@@ -1370,7 +1370,7 @@

diff --git a/src/main/java/com/amorgakco/backend/global/config/RabbitMQConfig.java b/src/main/java/com/amorgakco/backend/global/config/RabbitMQConfig.java index cb442e4..4b57bbe 100644 --- a/src/main/java/com/amorgakco/backend/global/config/RabbitMQConfig.java +++ b/src/main/java/com/amorgakco/backend/global/config/RabbitMQConfig.java @@ -18,11 +18,12 @@ import org.springframework.amqp.support.converter.MessageConverter; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Profile; @EnableRabbit @Configuration @RequiredArgsConstructor -//@Profile("!test") +@Profile("!test") public class RabbitMQConfig { private final RabbitMQProperties properties; diff --git a/src/main/resources/static/docs/index.html b/src/main/resources/static/docs/index.html index 23318fa..37f5c03 100644 --- a/src/main/resources/static/docs/index.html +++ b/src/main/resources/static/docs/index.html @@ -522,9 +522,9 @@

@@ -1370,7 +1370,7 @@

From 36f1ec13db0d9980f99885b1c5ef99811abfef9a Mon Sep 17 00:00:00 2001 From: songhaechan Date: Sun, 22 Sep 2024 17:24:13 +0900 Subject: [PATCH 06/22] =?UTF-8?q?test:=20testcontainer=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 3 +++ .../backend/container/IntegrationTest.java | 9 +++++++ .../container/TestContainerConfig.java | 27 +++++++++++++++++++ .../service/ParticipantServiceTest.java | 3 +++ 4 files changed, 42 insertions(+) create mode 100644 src/test/java/com/amorgakco/backend/container/IntegrationTest.java create mode 100644 src/test/java/com/amorgakco/backend/container/TestContainerConfig.java diff --git a/build.gradle b/build.gradle index 4d834bd..a029cac 100644 --- a/build.gradle +++ b/build.gradle @@ -56,6 +56,9 @@ dependencies { implementation group: 'org.springframework.boot', name: 'spring-boot-starter-validation' runtimeOnly 'com.h2database:h2' implementation 'org.redisson:redisson-spring-boot-starter:3.18.0' + testImplementation "org.junit.jupiter:junit-jupiter:5.8.1" + testImplementation "org.testcontainers:junit-jupiter:1.16.3" + testImplementation "com.redis:testcontainers-redis:2.0.1" } tasks.named('test') { diff --git a/src/test/java/com/amorgakco/backend/container/IntegrationTest.java b/src/test/java/com/amorgakco/backend/container/IntegrationTest.java new file mode 100644 index 0000000..fccc133 --- /dev/null +++ b/src/test/java/com/amorgakco/backend/container/IntegrationTest.java @@ -0,0 +1,9 @@ +package com.amorgakco.backend.container; + +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ContextConfiguration; + +@SpringBootTest +@ContextConfiguration(initializers = {TestContainerConfig.class}) +public @interface IntegrationTest { +} diff --git a/src/test/java/com/amorgakco/backend/container/TestContainerConfig.java b/src/test/java/com/amorgakco/backend/container/TestContainerConfig.java new file mode 100644 index 0000000..f8e2027 --- /dev/null +++ b/src/test/java/com/amorgakco/backend/container/TestContainerConfig.java @@ -0,0 +1,27 @@ +package com.amorgakco.backend.container; + +import com.redis.testcontainers.RedisContainer; +import org.springframework.boot.test.util.TestPropertyValues; +import org.springframework.context.ApplicationContextInitializer; +import org.springframework.context.ConfigurableApplicationContext; +import org.testcontainers.utility.DockerImageName; + +public class TestContainerConfig + implements ApplicationContextInitializer { + + private static final RedisContainer REDIS_CONTAINER = + new RedisContainer(DockerImageName.parse("redis:latest")).withExposedPorts(6379); + + static { + REDIS_CONTAINER.start(); + } + + @Override + public void initialize(final ConfigurableApplicationContext applicationContext) { + + TestPropertyValues.of( + "spring.data.redis.host=" + REDIS_CONTAINER.getHost(), + "spring.data.redis.port=" + REDIS_CONTAINER.getFirstMappedPort()) + .applyTo(applicationContext.getEnvironment()); + } +} \ No newline at end of file diff --git a/src/test/java/com/amorgakco/backend/participant/service/ParticipantServiceTest.java b/src/test/java/com/amorgakco/backend/participant/service/ParticipantServiceTest.java index 8aeebaa..5d9972f 100644 --- a/src/test/java/com/amorgakco/backend/participant/service/ParticipantServiceTest.java +++ b/src/test/java/com/amorgakco/backend/participant/service/ParticipantServiceTest.java @@ -1,5 +1,6 @@ package com.amorgakco.backend.participant.service; +import com.amorgakco.backend.container.TestContainerConfig; import com.amorgakco.backend.fixture.group.TestGroupFactory; import com.amorgakco.backend.group.domain.Group; import com.amorgakco.backend.group.repository.GroupRepository; @@ -11,6 +12,7 @@ import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ContextConfiguration; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; @@ -18,6 +20,7 @@ import java.util.concurrent.atomic.AtomicInteger; @SpringBootTest +@ContextConfiguration(initializers = {TestContainerConfig.class}) class ParticipantServiceTest { @Autowired From c0eb8090b47bd5d3d913415ab42950045b81047b Mon Sep 17 00:00:00 2001 From: songhaechan Date: Sun, 22 Sep 2024 17:40:02 +0900 Subject: [PATCH 07/22] =?UTF-8?q?test:=20workflow=20redis=20=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/amorgakco-ci.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.github/workflows/amorgakco-ci.yml b/.github/workflows/amorgakco-ci.yml index 959bf7d..927dc7d 100644 --- a/.github/workflows/amorgakco-ci.yml +++ b/.github/workflows/amorgakco-ci.yml @@ -10,10 +10,6 @@ jobs: build: runs-on: ubuntu-latest steps: - - name: Start Redis - uses: supercharge/redis-github-action@1.1.0 - with: - redis-version: 6 - uses: actions/checkout@v3 - uses: actions/setup-java@v3 with: From c8d8ee59d24f7936701e08e6744be7c45f16adbd Mon Sep 17 00:00:00 2001 From: songhaechan Date: Sun, 22 Sep 2024 17:57:22 +0900 Subject: [PATCH 08/22] test: redis test --- .../service/ParticipantServiceTest.java | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/test/java/com/amorgakco/backend/participant/service/ParticipantServiceTest.java b/src/test/java/com/amorgakco/backend/participant/service/ParticipantServiceTest.java index 5d9972f..74b9611 100644 --- a/src/test/java/com/amorgakco/backend/participant/service/ParticipantServiceTest.java +++ b/src/test/java/com/amorgakco/backend/participant/service/ParticipantServiceTest.java @@ -17,7 +17,6 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; -import java.util.concurrent.atomic.AtomicInteger; @SpringBootTest @ContextConfiguration(initializers = {TestContainerConfig.class}) @@ -30,6 +29,12 @@ class ParticipantServiceTest { @Autowired private GroupRepository groupRepository; + @Test + @DisplayName("") + void test() { + Member member1 = memberRepository.save(Member.builder().nickname("member1").build()); + } + @Test @DisplayName("멀티 스레드 환경에서 온도를 상승시킨 횟수 만큼 온도가 상승돼야한다.") @@ -44,16 +49,12 @@ void moGakCoTemperatureConcurrencyTest() throws InterruptedException { ExecutorService executorService = Executors.newFixedThreadPool(memberCount); CountDownLatch latch = new CountDownLatch(memberCount); - AtomicInteger successCount = new AtomicInteger(); - AtomicInteger failCount = new AtomicInteger(); for (int i = 0; i < memberCount; i++) { executorService.execute(() -> { try { participantService.upTemperature(1L, 1L, 2L); - successCount.incrementAndGet(); } catch (Exception e) { - failCount.incrementAndGet(); } finally { latch.countDown(); } @@ -61,12 +62,9 @@ void moGakCoTemperatureConcurrencyTest() throws InterruptedException { } latch.await(); - System.out.println("failCount = " + failCount); - System.out.println("successCount = " + successCount); Member member = memberRepository.findById(2L).get(); Integer moGakCoTemperature = member.getMoGakCoTemperature(); - System.out.println("moGakCoTemperature = " + moGakCoTemperature); Assertions.assertThat(moGakCoTemperature).isEqualTo(memberCount); } } \ No newline at end of file From ed5dd329e5d8249ca8b449211c2948dac2589070 Mon Sep 17 00:00:00 2001 From: songhaechan Date: Sun, 22 Sep 2024 18:00:26 +0900 Subject: [PATCH 09/22] test: inmemory h2 test --- .../service/ParticipantServiceTest.java | 74 ++++++++----------- 1 file changed, 32 insertions(+), 42 deletions(-) diff --git a/src/test/java/com/amorgakco/backend/participant/service/ParticipantServiceTest.java b/src/test/java/com/amorgakco/backend/participant/service/ParticipantServiceTest.java index 74b9611..293d156 100644 --- a/src/test/java/com/amorgakco/backend/participant/service/ParticipantServiceTest.java +++ b/src/test/java/com/amorgakco/backend/participant/service/ParticipantServiceTest.java @@ -1,25 +1,15 @@ package com.amorgakco.backend.participant.service; -import com.amorgakco.backend.container.TestContainerConfig; -import com.amorgakco.backend.fixture.group.TestGroupFactory; -import com.amorgakco.backend.group.domain.Group; import com.amorgakco.backend.group.repository.GroupRepository; import com.amorgakco.backend.member.domain.Member; import com.amorgakco.backend.member.repository.MemberRepository; -import com.amorgakco.backend.participant.domain.Participant; -import org.assertj.core.api.Assertions; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.ContextConfiguration; - -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; @SpringBootTest -@ContextConfiguration(initializers = {TestContainerConfig.class}) +//@ContextConfiguration(initializers = {TestContainerConfig.class}) class ParticipantServiceTest { @Autowired @@ -36,35 +26,35 @@ void test() { } - @Test - @DisplayName("멀티 스레드 환경에서 온도를 상승시킨 횟수 만큼 온도가 상승돼야한다.") - void moGakCoTemperatureConcurrencyTest() throws InterruptedException { - Member member1 = memberRepository.save(Member.builder().nickname("member1").build()); - Member member2 = memberRepository.save(Member.builder().nickname("member2").build()); - Group group = TestGroupFactory.create(member1); - group.addParticipants(new Participant(member2)); - groupRepository.saveAndFlush(group); - - int memberCount = 20; - - ExecutorService executorService = Executors.newFixedThreadPool(memberCount); - CountDownLatch latch = new CountDownLatch(memberCount); - - for (int i = 0; i < memberCount; i++) { - executorService.execute(() -> { - try { - participantService.upTemperature(1L, 1L, 2L); - } catch (Exception e) { - } finally { - latch.countDown(); - } - }); - } - - latch.await(); - - Member member = memberRepository.findById(2L).get(); - Integer moGakCoTemperature = member.getMoGakCoTemperature(); - Assertions.assertThat(moGakCoTemperature).isEqualTo(memberCount); - } +// @Test +// @DisplayName("멀티 스레드 환경에서 온도를 상승시킨 횟수 만큼 온도가 상승돼야한다.") +// void moGakCoTemperatureConcurrencyTest() throws InterruptedException { +// Member member1 = memberRepository.save(Member.builder().nickname("member1").build()); +// Member member2 = memberRepository.save(Member.builder().nickname("member2").build()); +// Group group = TestGroupFactory.create(member1); +// group.addParticipants(new Participant(member2)); +// groupRepository.saveAndFlush(group); +// +// int memberCount = 20; +// +// ExecutorService executorService = Executors.newFixedThreadPool(memberCount); +// CountDownLatch latch = new CountDownLatch(memberCount); +// +// for (int i = 0; i < memberCount; i++) { +// executorService.execute(() -> { +// try { +// participantService.upTemperature(1L, 1L, 2L); +// } catch (Exception e) { +// } finally { +// latch.countDown(); +// } +// }); +// } +// +// latch.await(); +// +// Member member = memberRepository.findById(2L).get(); +// Integer moGakCoTemperature = member.getMoGakCoTemperature(); +// Assertions.assertThat(moGakCoTemperature).isEqualTo(memberCount); +// } } \ No newline at end of file From daf075f3786a0c063e029176f7c27f2b0d86f789 Mon Sep 17 00:00:00 2001 From: songhaechan Date: Sun, 22 Sep 2024 18:11:00 +0900 Subject: [PATCH 10/22] test: redis test --- .../backend/participant/service/ParticipantServiceTest.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/test/java/com/amorgakco/backend/participant/service/ParticipantServiceTest.java b/src/test/java/com/amorgakco/backend/participant/service/ParticipantServiceTest.java index 293d156..4f18b0d 100644 --- a/src/test/java/com/amorgakco/backend/participant/service/ParticipantServiceTest.java +++ b/src/test/java/com/amorgakco/backend/participant/service/ParticipantServiceTest.java @@ -1,5 +1,6 @@ package com.amorgakco.backend.participant.service; +import com.amorgakco.backend.container.TestContainerConfig; import com.amorgakco.backend.group.repository.GroupRepository; import com.amorgakco.backend.member.domain.Member; import com.amorgakco.backend.member.repository.MemberRepository; @@ -7,9 +8,10 @@ import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ContextConfiguration; @SpringBootTest -//@ContextConfiguration(initializers = {TestContainerConfig.class}) +@ContextConfiguration(initializers = {TestContainerConfig.class}) class ParticipantServiceTest { @Autowired From 176f0ccac2bee026c25afd32d7068e8497713420 Mon Sep 17 00:00:00 2001 From: songhaechan Date: Sun, 22 Sep 2024 21:05:37 +0900 Subject: [PATCH 11/22] test: redis testcontainer --- .../amorgakco/backend/container/TestContainerConfig.java | 2 +- src/test/resources/application-test.yml | 9 --------- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/src/test/java/com/amorgakco/backend/container/TestContainerConfig.java b/src/test/java/com/amorgakco/backend/container/TestContainerConfig.java index f8e2027..9866681 100644 --- a/src/test/java/com/amorgakco/backend/container/TestContainerConfig.java +++ b/src/test/java/com/amorgakco/backend/container/TestContainerConfig.java @@ -6,6 +6,7 @@ import org.springframework.context.ConfigurableApplicationContext; import org.testcontainers.utility.DockerImageName; + public class TestContainerConfig implements ApplicationContextInitializer { @@ -18,7 +19,6 @@ public class TestContainerConfig @Override public void initialize(final ConfigurableApplicationContext applicationContext) { - TestPropertyValues.of( "spring.data.redis.host=" + REDIS_CONTAINER.getHost(), "spring.data.redis.port=" + REDIS_CONTAINER.getFirstMappedPort()) diff --git a/src/test/resources/application-test.yml b/src/test/resources/application-test.yml index 7f3833a..e5ea937 100644 --- a/src/test/resources/application-test.yml +++ b/src/test/resources/application-test.yml @@ -17,14 +17,5 @@ spring: hibernate: dialect: org.hibernate.dialect.MySQLDialect defer-datasource-initialization: true - data: - redis: - host: localhost - port: 6379 - rabbitmq: - host: localhost - port: 5672 - username: "guest" - password: "guest" fcm-secret-path: fcm-secret.json \ No newline at end of file From 790e547ad80a25c113726c6e816c24720f837f58 Mon Sep 17 00:00:00 2001 From: songhaechan Date: Sun, 22 Sep 2024 21:11:58 +0900 Subject: [PATCH 12/22] test: redis testcontainer --- build.gradle | 1 + .../container/TestContainerConfig.java | 15 +++- .../service/ParticipantServiceTest.java | 70 ++++++++++--------- src/test/resources/application-test.yml | 12 ++-- 4 files changed, 57 insertions(+), 41 deletions(-) diff --git a/build.gradle b/build.gradle index a029cac..ca525e0 100644 --- a/build.gradle +++ b/build.gradle @@ -59,6 +59,7 @@ dependencies { testImplementation "org.junit.jupiter:junit-jupiter:5.8.1" testImplementation "org.testcontainers:junit-jupiter:1.16.3" testImplementation "com.redis:testcontainers-redis:2.0.1" + testImplementation "org.testcontainers:mysql:1.17.2" } tasks.named('test') { diff --git a/src/test/java/com/amorgakco/backend/container/TestContainerConfig.java b/src/test/java/com/amorgakco/backend/container/TestContainerConfig.java index 9866681..654de09 100644 --- a/src/test/java/com/amorgakco/backend/container/TestContainerConfig.java +++ b/src/test/java/com/amorgakco/backend/container/TestContainerConfig.java @@ -4,6 +4,7 @@ import org.springframework.boot.test.util.TestPropertyValues; import org.springframework.context.ApplicationContextInitializer; import org.springframework.context.ConfigurableApplicationContext; +import org.testcontainers.containers.MySQLContainer; import org.testcontainers.utility.DockerImageName; @@ -12,16 +13,28 @@ public class TestContainerConfig private static final RedisContainer REDIS_CONTAINER = new RedisContainer(DockerImageName.parse("redis:latest")).withExposedPorts(6379); + private static final MySQLContainer MYSQL_CONTAINER = + new MySQLContainer(DockerImageName.parse("mysql:8.0.22")) + .withDatabaseName("amorgakco") + .withUsername("admin") + .withPassword("1234"); static { REDIS_CONTAINER.start(); + MYSQL_CONTAINER.start(); } @Override public void initialize(final ConfigurableApplicationContext applicationContext) { + final String jdbcUrl = MYSQL_CONTAINER.getJdbcUrl(); + final String username = MYSQL_CONTAINER.getUsername(); + final String password = MYSQL_CONTAINER.getPassword(); TestPropertyValues.of( "spring.data.redis.host=" + REDIS_CONTAINER.getHost(), - "spring.data.redis.port=" + REDIS_CONTAINER.getFirstMappedPort()) + "spring.data.redis.port=" + REDIS_CONTAINER.getFirstMappedPort(), + "spring.datasource.url=" + jdbcUrl, + "spring.datasource.username=" + username, + "spring.datasource.password=" + password) .applyTo(applicationContext.getEnvironment()); } } \ No newline at end of file diff --git a/src/test/java/com/amorgakco/backend/participant/service/ParticipantServiceTest.java b/src/test/java/com/amorgakco/backend/participant/service/ParticipantServiceTest.java index 4f18b0d..d82b0f8 100644 --- a/src/test/java/com/amorgakco/backend/participant/service/ParticipantServiceTest.java +++ b/src/test/java/com/amorgakco/backend/participant/service/ParticipantServiceTest.java @@ -1,15 +1,23 @@ package com.amorgakco.backend.participant.service; import com.amorgakco.backend.container.TestContainerConfig; +import com.amorgakco.backend.fixture.group.TestGroupFactory; +import com.amorgakco.backend.group.domain.Group; import com.amorgakco.backend.group.repository.GroupRepository; import com.amorgakco.backend.member.domain.Member; import com.amorgakco.backend.member.repository.MemberRepository; +import com.amorgakco.backend.participant.domain.Participant; +import org.assertj.core.api.Assertions; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.ContextConfiguration; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + @SpringBootTest @ContextConfiguration(initializers = {TestContainerConfig.class}) class ParticipantServiceTest { @@ -21,42 +29,36 @@ class ParticipantServiceTest { @Autowired private GroupRepository groupRepository; + @Test - @DisplayName("") - void test() { + @DisplayName("멀티 스레드 환경에서 온도를 상승시킨 횟수 만큼 온도가 상승돼야한다.") + void moGakCoTemperatureConcurrencyTest() throws InterruptedException { Member member1 = memberRepository.save(Member.builder().nickname("member1").build()); - } + Member member2 = memberRepository.save(Member.builder().nickname("member2").build()); + Group group = TestGroupFactory.create(member1); + group.addParticipants(new Participant(member2)); + groupRepository.saveAndFlush(group); + + int memberCount = 20; + ExecutorService executorService = Executors.newFixedThreadPool(memberCount); + CountDownLatch latch = new CountDownLatch(memberCount); -// @Test -// @DisplayName("멀티 스레드 환경에서 온도를 상승시킨 횟수 만큼 온도가 상승돼야한다.") -// void moGakCoTemperatureConcurrencyTest() throws InterruptedException { -// Member member1 = memberRepository.save(Member.builder().nickname("member1").build()); -// Member member2 = memberRepository.save(Member.builder().nickname("member2").build()); -// Group group = TestGroupFactory.create(member1); -// group.addParticipants(new Participant(member2)); -// groupRepository.saveAndFlush(group); -// -// int memberCount = 20; -// -// ExecutorService executorService = Executors.newFixedThreadPool(memberCount); -// CountDownLatch latch = new CountDownLatch(memberCount); -// -// for (int i = 0; i < memberCount; i++) { -// executorService.execute(() -> { -// try { -// participantService.upTemperature(1L, 1L, 2L); -// } catch (Exception e) { -// } finally { -// latch.countDown(); -// } -// }); -// } -// -// latch.await(); -// -// Member member = memberRepository.findById(2L).get(); -// Integer moGakCoTemperature = member.getMoGakCoTemperature(); -// Assertions.assertThat(moGakCoTemperature).isEqualTo(memberCount); -// } + for (int i = 0; i < memberCount; i++) { + executorService.execute(() -> { + try { + participantService.upTemperature(1L, 1L, 2L); + } catch (Exception e) { + } finally { + latch.countDown(); + } + }); + } + + latch.await(); + + Member member = memberRepository.findById(2L).get(); + Integer moGakCoTemperature = member.getMoGakCoTemperature(); + Assertions.assertThat(moGakCoTemperature).isEqualTo(memberCount); + } } \ No newline at end of file diff --git a/src/test/resources/application-test.yml b/src/test/resources/application-test.yml index e5ea937..5151157 100644 --- a/src/test/resources/application-test.yml +++ b/src/test/resources/application-test.yml @@ -2,12 +2,12 @@ spring: config: activate: on-profile: test - datasource: - driver-class-name: org.h2.Driver - url: - jdbc:h2:mem:amorgakco;MODE=MySQL; - username: sa - password: + # datasource: + # driver-class-name: org.h2.Driver + # url: + # jdbc:h2:mem:amorgakco;MODE=MySQL; + # username: sa + # password: jpa: show-sql: true hibernate: From 105d94ee92ea59a9d912049019d5865323240dbb Mon Sep 17 00:00:00 2001 From: songhaechan Date: Sun, 22 Sep 2024 21:35:44 +0900 Subject: [PATCH 13/22] test: redis testcontainer --- .../backend/global/config/redisson/RedissonConfig.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/com/amorgakco/backend/global/config/redisson/RedissonConfig.java b/src/main/java/com/amorgakco/backend/global/config/redisson/RedissonConfig.java index 21ab98b..26d0458 100644 --- a/src/main/java/com/amorgakco/backend/global/config/redisson/RedissonConfig.java +++ b/src/main/java/com/amorgakco/backend/global/config/redisson/RedissonConfig.java @@ -5,7 +5,9 @@ import org.redisson.config.Config; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +@Configuration public class RedissonConfig { private static final String REDISSON_HOST_PREFIX = "redis://"; @Value("${spring.redis.host}") From f9853b0206ddc06ca162af43b2e81bd50951daa2 Mon Sep 17 00:00:00 2001 From: songhaechan Date: Sun, 22 Sep 2024 22:02:11 +0900 Subject: [PATCH 14/22] test: redis testcontainer --- .../config/redisson/RedissonConfig.java | 2 ++ .../container/TestContainerConfig.java | 35 ++++++++++--------- src/test/resources/application-test.yml | 12 +++---- 3 files changed, 27 insertions(+), 22 deletions(-) diff --git a/src/main/java/com/amorgakco/backend/global/config/redisson/RedissonConfig.java b/src/main/java/com/amorgakco/backend/global/config/redisson/RedissonConfig.java index 26d0458..3e03348 100644 --- a/src/main/java/com/amorgakco/backend/global/config/redisson/RedissonConfig.java +++ b/src/main/java/com/amorgakco/backend/global/config/redisson/RedissonConfig.java @@ -6,8 +6,10 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Profile; @Configuration +@Profile("!test") public class RedissonConfig { private static final String REDISSON_HOST_PREFIX = "redis://"; @Value("${spring.redis.host}") diff --git a/src/test/java/com/amorgakco/backend/container/TestContainerConfig.java b/src/test/java/com/amorgakco/backend/container/TestContainerConfig.java index 654de09..c284671 100644 --- a/src/test/java/com/amorgakco/backend/container/TestContainerConfig.java +++ b/src/test/java/com/amorgakco/backend/container/TestContainerConfig.java @@ -1,40 +1,43 @@ package com.amorgakco.backend.container; import com.redis.testcontainers.RedisContainer; +import org.redisson.Redisson; +import org.redisson.api.RedissonClient; +import org.redisson.config.Config; import org.springframework.boot.test.util.TestPropertyValues; import org.springframework.context.ApplicationContextInitializer; import org.springframework.context.ConfigurableApplicationContext; -import org.testcontainers.containers.MySQLContainer; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Profile; import org.testcontainers.utility.DockerImageName; - +@Configuration +@Profile("test") public class TestContainerConfig implements ApplicationContextInitializer { + private static final String REDISSON_HOST_PREFIX = "redis://"; private static final RedisContainer REDIS_CONTAINER = - new RedisContainer(DockerImageName.parse("redis:latest")).withExposedPorts(6379); - private static final MySQLContainer MYSQL_CONTAINER = - new MySQLContainer(DockerImageName.parse("mysql:8.0.22")) - .withDatabaseName("amorgakco") - .withUsername("admin") - .withPassword("1234"); + new RedisContainer(DockerImageName.parse("redis:latest")) + .withExposedPorts(6379); + + @Bean + public RedissonClient redissonClient() { + Config config = new Config(); + config.useSingleServer().setAddress(REDISSON_HOST_PREFIX + REDIS_CONTAINER.getHost() + ":" + REDIS_CONTAINER.getFirstMappedPort()); + return Redisson.create(config); + } static { REDIS_CONTAINER.start(); - MYSQL_CONTAINER.start(); } @Override public void initialize(final ConfigurableApplicationContext applicationContext) { - final String jdbcUrl = MYSQL_CONTAINER.getJdbcUrl(); - final String username = MYSQL_CONTAINER.getUsername(); - final String password = MYSQL_CONTAINER.getPassword(); TestPropertyValues.of( "spring.data.redis.host=" + REDIS_CONTAINER.getHost(), - "spring.data.redis.port=" + REDIS_CONTAINER.getFirstMappedPort(), - "spring.datasource.url=" + jdbcUrl, - "spring.datasource.username=" + username, - "spring.datasource.password=" + password) + "spring.data.redis.port=" + REDIS_CONTAINER.getFirstMappedPort()) .applyTo(applicationContext.getEnvironment()); } } \ No newline at end of file diff --git a/src/test/resources/application-test.yml b/src/test/resources/application-test.yml index 5151157..e5ea937 100644 --- a/src/test/resources/application-test.yml +++ b/src/test/resources/application-test.yml @@ -2,12 +2,12 @@ spring: config: activate: on-profile: test - # datasource: - # driver-class-name: org.h2.Driver - # url: - # jdbc:h2:mem:amorgakco;MODE=MySQL; - # username: sa - # password: + datasource: + driver-class-name: org.h2.Driver + url: + jdbc:h2:mem:amorgakco;MODE=MySQL; + username: sa + password: jpa: show-sql: true hibernate: From 884d1892992d480135ac23a83e847b930005b2d1 Mon Sep 17 00:00:00 2001 From: songhaechan Date: Sun, 22 Sep 2024 22:28:03 +0900 Subject: [PATCH 15/22] =?UTF-8?q?test:=20ci=20workflow=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/amorgakco-ci.yml | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/.github/workflows/amorgakco-ci.yml b/.github/workflows/amorgakco-ci.yml index 927dc7d..aa54d25 100644 --- a/.github/workflows/amorgakco-ci.yml +++ b/.github/workflows/amorgakco-ci.yml @@ -5,7 +5,10 @@ on: - main permissions: write-all - +defaults: + run: + shell: bash + working-directory: ./backend jobs: build: runs-on: ubuntu-latest @@ -15,6 +18,13 @@ jobs: with: java-version: '17' distribution: 'temurin' + - name: Apply Environment Variables + run: | + mkdir -p src/test/resources + echo "${{ secrets.APPLICATION_JWT }}" > src/test/resources/application-jwt.yml + echo "${{ secrets.APPLICATION_OAUTH2 }}" > src/test/resources/application-oauth2.yml + echo "${{ secrets.FCM_SECRET }}" > src/test/resources/fcm-secret.json + echo "${{ secrets.APPLICATION_NOTIFICATION }}" > src/test/resources/application-notification.yml - run: chmod +x gradlew - run: ./gradlew build - name: 테스트 커버리지를 PR에 코멘트에 등록 From 8d54b368cd707ffbc978cef2eac854a5959a8f13 Mon Sep 17 00:00:00 2001 From: songhaechan Date: Sun, 22 Sep 2024 22:29:04 +0900 Subject: [PATCH 16/22] =?UTF-8?q?test:=20ci=20workflow=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/amorgakco-ci.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.github/workflows/amorgakco-ci.yml b/.github/workflows/amorgakco-ci.yml index aa54d25..638e47c 100644 --- a/.github/workflows/amorgakco-ci.yml +++ b/.github/workflows/amorgakco-ci.yml @@ -5,10 +5,6 @@ on: - main permissions: write-all -defaults: - run: - shell: bash - working-directory: ./backend jobs: build: runs-on: ubuntu-latest From 67483bd5616c6317f5ba6c4f185441d76191a8b6 Mon Sep 17 00:00:00 2001 From: songhaechan Date: Sun, 22 Sep 2024 22:40:22 +0900 Subject: [PATCH 17/22] =?UTF-8?q?test:=20ci=20workflow=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/amorgakco-ci.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/amorgakco-ci.yml b/.github/workflows/amorgakco-ci.yml index 638e47c..74e10ba 100644 --- a/.github/workflows/amorgakco-ci.yml +++ b/.github/workflows/amorgakco-ci.yml @@ -17,10 +17,15 @@ jobs: - name: Apply Environment Variables run: | mkdir -p src/test/resources + mkdir -p src/main/resources echo "${{ secrets.APPLICATION_JWT }}" > src/test/resources/application-jwt.yml echo "${{ secrets.APPLICATION_OAUTH2 }}" > src/test/resources/application-oauth2.yml echo "${{ secrets.FCM_SECRET }}" > src/test/resources/fcm-secret.json echo "${{ secrets.APPLICATION_NOTIFICATION }}" > src/test/resources/application-notification.yml + echo "${{ secrets.APPLICATION_JWT }}" > src/main/resources/application-jwt.yml + echo "${{ secrets.APPLICATION_OAUTH2 }}" > src/main/resources/application-oauth2.yml + echo "${{ secrets.FCM_SECRET }}" > src/main/resources/fcm-secret.json + echo "${{ secrets.APPLICATION_NOTIFICATION }}" > src/main/resources/application-notification.yml - run: chmod +x gradlew - run: ./gradlew build - name: 테스트 커버리지를 PR에 코멘트에 등록 From f874f9b80c61205f988dc6c0d99b6e1724dfdf0d Mon Sep 17 00:00:00 2001 From: songhaechan Date: Sun, 22 Sep 2024 22:50:00 +0900 Subject: [PATCH 18/22] =?UTF-8?q?test:=20ci=20workflow=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/amorgakco-ci.yml | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/.github/workflows/amorgakco-ci.yml b/.github/workflows/amorgakco-ci.yml index 74e10ba..7823906 100644 --- a/.github/workflows/amorgakco-ci.yml +++ b/.github/workflows/amorgakco-ci.yml @@ -16,16 +16,14 @@ jobs: distribution: 'temurin' - name: Apply Environment Variables run: | - mkdir -p src/test/resources - mkdir -p src/main/resources echo "${{ secrets.APPLICATION_JWT }}" > src/test/resources/application-jwt.yml echo "${{ secrets.APPLICATION_OAUTH2 }}" > src/test/resources/application-oauth2.yml echo "${{ secrets.FCM_SECRET }}" > src/test/resources/fcm-secret.json echo "${{ secrets.APPLICATION_NOTIFICATION }}" > src/test/resources/application-notification.yml echo "${{ secrets.APPLICATION_JWT }}" > src/main/resources/application-jwt.yml - echo "${{ secrets.APPLICATION_OAUTH2 }}" > src/main/resources/application-oauth2.yml - echo "${{ secrets.FCM_SECRET }}" > src/main/resources/fcm-secret.json - echo "${{ secrets.APPLICATION_NOTIFICATION }}" > src/main/resources/application-notification.yml + echo "${{ secrets.APPLICATION_OAUTH2 }}" > src/main/resources/application-oauth2.yml + echo "${{ secrets.FCM_SECRET }}" > src/main/resources/fcm-secret.json + echo "${{ secrets.APPLICATION_NOTIFICATION }}" > src/main/resources/application-notification.yml - run: chmod +x gradlew - run: ./gradlew build - name: 테스트 커버리지를 PR에 코멘트에 등록 From eba7ed92189d23eb625bb7767e0dbab30e5bc1a9 Mon Sep 17 00:00:00 2001 From: songhaechan Date: Sun, 22 Sep 2024 22:53:45 +0900 Subject: [PATCH 19/22] =?UTF-8?q?test:=20ci=20workflow=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/amorgakco-ci.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/amorgakco-ci.yml b/.github/workflows/amorgakco-ci.yml index 7823906..8b8a3e5 100644 --- a/.github/workflows/amorgakco-ci.yml +++ b/.github/workflows/amorgakco-ci.yml @@ -16,14 +16,14 @@ jobs: distribution: 'temurin' - name: Apply Environment Variables run: | - echo "${{ secrets.APPLICATION_JWT }}" > src/test/resources/application-jwt.yml - echo "${{ secrets.APPLICATION_OAUTH2 }}" > src/test/resources/application-oauth2.yml - echo "${{ secrets.FCM_SECRET }}" > src/test/resources/fcm-secret.json - echo "${{ secrets.APPLICATION_NOTIFICATION }}" > src/test/resources/application-notification.yml - echo "${{ secrets.APPLICATION_JWT }}" > src/main/resources/application-jwt.yml - echo "${{ secrets.APPLICATION_OAUTH2 }}" > src/main/resources/application-oauth2.yml - echo "${{ secrets.FCM_SECRET }}" > src/main/resources/fcm-secret.json - echo "${{ secrets.APPLICATION_NOTIFICATION }}" > src/main/resources/application-notification.yml + echo "${{ secrets.APPLICATION_JWT }}" > ./src/test/resources/application-jwt.yml + echo "${{ secrets.APPLICATION_OAUTH2 }}" > ./src/test/resources/application-oauth2.yml + echo "${{ secrets.FCM_SECRET }}" > ./src/test/resources/fcm-secret.json + echo "${{ secrets.APPLICATION_NOTIFICATION }}" > ./src/test/resources/application-notification.yml + echo "${{ secrets.APPLICATION_JWT }}" > ./src/main/resources/application-jwt.yml + echo "${{ secrets.APPLICATION_OAUTH2 }}" > ./src/main/resources/application-oauth2.yml + echo "${{ secrets.FCM_SECRET }}" > ./src/main/resources/fcm-secret.json + echo "${{ secrets.APPLICATION_NOTIFICATION }}" > ./src/main/resources/application-notification.yml - run: chmod +x gradlew - run: ./gradlew build - name: 테스트 커버리지를 PR에 코멘트에 등록 From afea053d3c0364d46f5f82fc7a1aa3d6e8c864ec Mon Sep 17 00:00:00 2001 From: songhaechan Date: Sun, 22 Sep 2024 22:58:53 +0900 Subject: [PATCH 20/22] =?UTF-8?q?test:=20ci=20workflow=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/amorgakco-ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/amorgakco-ci.yml b/.github/workflows/amorgakco-ci.yml index 8b8a3e5..0bdded0 100644 --- a/.github/workflows/amorgakco-ci.yml +++ b/.github/workflows/amorgakco-ci.yml @@ -18,11 +18,11 @@ jobs: run: | echo "${{ secrets.APPLICATION_JWT }}" > ./src/test/resources/application-jwt.yml echo "${{ secrets.APPLICATION_OAUTH2 }}" > ./src/test/resources/application-oauth2.yml - echo "${{ secrets.FCM_SECRET }}" > ./src/test/resources/fcm-secret.json + echo "${{ secrets.FCM_SECRET }}" | base64 -d > ./src/test/resources/fcm-secret.json echo "${{ secrets.APPLICATION_NOTIFICATION }}" > ./src/test/resources/application-notification.yml echo "${{ secrets.APPLICATION_JWT }}" > ./src/main/resources/application-jwt.yml echo "${{ secrets.APPLICATION_OAUTH2 }}" > ./src/main/resources/application-oauth2.yml - echo "${{ secrets.FCM_SECRET }}" > ./src/main/resources/fcm-secret.json + echo "${{ secrets.FCM_SECRET }}" | base64 -d > ./src/main/resources/fcm-secret.json echo "${{ secrets.APPLICATION_NOTIFICATION }}" > ./src/main/resources/application-notification.yml - run: chmod +x gradlew - run: ./gradlew build From 5732e03970c0a3f02875ebc2ee353b5c2311bd2b Mon Sep 17 00:00:00 2001 From: songhaechan Date: Sun, 22 Sep 2024 23:09:50 +0900 Subject: [PATCH 21/22] =?UTF-8?q?test:=20ci=20workflow=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/amorgakco-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/amorgakco-ci.yml b/.github/workflows/amorgakco-ci.yml index 0bdded0..bfa8179 100644 --- a/.github/workflows/amorgakco-ci.yml +++ b/.github/workflows/amorgakco-ci.yml @@ -21,8 +21,8 @@ jobs: echo "${{ secrets.FCM_SECRET }}" | base64 -d > ./src/test/resources/fcm-secret.json echo "${{ secrets.APPLICATION_NOTIFICATION }}" > ./src/test/resources/application-notification.yml echo "${{ secrets.APPLICATION_JWT }}" > ./src/main/resources/application-jwt.yml + echo "${{ secrets.FCM_SECRET }}" | base64 -d > ./src/test/resources/fcm-secret.json echo "${{ secrets.APPLICATION_OAUTH2 }}" > ./src/main/resources/application-oauth2.yml - echo "${{ secrets.FCM_SECRET }}" | base64 -d > ./src/main/resources/fcm-secret.json echo "${{ secrets.APPLICATION_NOTIFICATION }}" > ./src/main/resources/application-notification.yml - run: chmod +x gradlew - run: ./gradlew build From 1dadadc51844705c133cd3191a5c09f2b7eab8ac Mon Sep 17 00:00:00 2001 From: songhaechan Date: Tue, 24 Sep 2024 15:41:15 +0900 Subject: [PATCH 22/22] =?UTF-8?q?setting:=20cd=20workflow=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/amorgakco-cd.yml | 1 + .../global/config/redisson/RedissonConfig.java | 7 +++---- src/main/resources/application-dev.yml | 2 +- .../backend/container/IntegrationTest.java | 9 --------- .../backend/container/TestContainerConfig.java | 17 ----------------- .../service/ParticipantServiceTest.java | 2 +- 6 files changed, 6 insertions(+), 32 deletions(-) delete mode 100644 src/test/java/com/amorgakco/backend/container/IntegrationTest.java diff --git a/.github/workflows/amorgakco-cd.yml b/.github/workflows/amorgakco-cd.yml index 72317ec..a46133d 100644 --- a/.github/workflows/amorgakco-cd.yml +++ b/.github/workflows/amorgakco-cd.yml @@ -18,4 +18,5 @@ jobs: cd Backend git pull sudo docker-compose down + sudo docker images prune sudo docker-compose up -d --build \ No newline at end of file diff --git a/src/main/java/com/amorgakco/backend/global/config/redisson/RedissonConfig.java b/src/main/java/com/amorgakco/backend/global/config/redisson/RedissonConfig.java index 3e03348..ef68641 100644 --- a/src/main/java/com/amorgakco/backend/global/config/redisson/RedissonConfig.java +++ b/src/main/java/com/amorgakco/backend/global/config/redisson/RedissonConfig.java @@ -6,15 +6,14 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Profile; @Configuration -@Profile("!test") public class RedissonConfig { private static final String REDISSON_HOST_PREFIX = "redis://"; - @Value("${spring.redis.host}") + + @Value("${spring.data.redis.host}") private String redisHost; - @Value("${spring.redis.port}") + @Value("${spring.data.redis.port}") private int redisPort; @Bean diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml index 81edddf..e9d3082 100644 --- a/src/main/resources/application-dev.yml +++ b/src/main/resources/application-dev.yml @@ -10,7 +10,7 @@ spring: jpa: show-sql: true hibernate: - ddl-auto: create + ddl-auto: none properties: hibernate: format_sql: true diff --git a/src/test/java/com/amorgakco/backend/container/IntegrationTest.java b/src/test/java/com/amorgakco/backend/container/IntegrationTest.java deleted file mode 100644 index fccc133..0000000 --- a/src/test/java/com/amorgakco/backend/container/IntegrationTest.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.amorgakco.backend.container; - -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.ContextConfiguration; - -@SpringBootTest -@ContextConfiguration(initializers = {TestContainerConfig.class}) -public @interface IntegrationTest { -} diff --git a/src/test/java/com/amorgakco/backend/container/TestContainerConfig.java b/src/test/java/com/amorgakco/backend/container/TestContainerConfig.java index c284671..a11ddf9 100644 --- a/src/test/java/com/amorgakco/backend/container/TestContainerConfig.java +++ b/src/test/java/com/amorgakco/backend/container/TestContainerConfig.java @@ -1,34 +1,17 @@ package com.amorgakco.backend.container; import com.redis.testcontainers.RedisContainer; -import org.redisson.Redisson; -import org.redisson.api.RedissonClient; -import org.redisson.config.Config; import org.springframework.boot.test.util.TestPropertyValues; import org.springframework.context.ApplicationContextInitializer; import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Profile; import org.testcontainers.utility.DockerImageName; -@Configuration -@Profile("test") public class TestContainerConfig implements ApplicationContextInitializer { - - private static final String REDISSON_HOST_PREFIX = "redis://"; private static final RedisContainer REDIS_CONTAINER = new RedisContainer(DockerImageName.parse("redis:latest")) .withExposedPorts(6379); - @Bean - public RedissonClient redissonClient() { - Config config = new Config(); - config.useSingleServer().setAddress(REDISSON_HOST_PREFIX + REDIS_CONTAINER.getHost() + ":" + REDIS_CONTAINER.getFirstMappedPort()); - return Redisson.create(config); - } - static { REDIS_CONTAINER.start(); } diff --git a/src/test/java/com/amorgakco/backend/participant/service/ParticipantServiceTest.java b/src/test/java/com/amorgakco/backend/participant/service/ParticipantServiceTest.java index d82b0f8..305591f 100644 --- a/src/test/java/com/amorgakco/backend/participant/service/ParticipantServiceTest.java +++ b/src/test/java/com/amorgakco/backend/participant/service/ParticipantServiceTest.java @@ -39,7 +39,7 @@ void moGakCoTemperatureConcurrencyTest() throws InterruptedException { group.addParticipants(new Participant(member2)); groupRepository.saveAndFlush(group); - int memberCount = 20; + int memberCount = 1; ExecutorService executorService = Executors.newFixedThreadPool(memberCount); CountDownLatch latch = new CountDownLatch(memberCount);