From 80ccbd9ffee7d8361ab91c6489b3a922ab0115a5 Mon Sep 17 00:00:00 2001 From: KWY Date: Wed, 8 May 2024 23:04:55 +0900 Subject: [PATCH 01/50] =?UTF-8?q?#259=20[chore]=20redisson=20=EC=9D=98?= =?UTF-8?q?=EC=A1=B4=EC=84=B1=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 82f43f2b..49fb1349 100644 --- a/build.gradle +++ b/build.gradle @@ -22,7 +22,9 @@ repositories { } dependencies { -// QueryDSL Implementation + implementation "org.redisson:redisson:3.29.0" + + // QueryDSL Implementation implementation 'com.querydsl:querydsl-jpa:5.0.0:jakarta' annotationProcessor "com.querydsl:querydsl-apt:${dependencyManagement.importedProperties['querydsl.version']}:jakarta" annotationProcessor "jakarta.annotation:jakarta.annotation-api" From dd691bebf256c695ba53beb701d7c614169e42b6 Mon Sep 17 00:00:00 2001 From: KWY Date: Wed, 8 May 2024 23:05:10 +0900 Subject: [PATCH 02/50] =?UTF-8?q?#259=20[feat]=20redis=20config=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../asap/server/config/redis/RedisConfig.java | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 src/main/java/com/asap/server/config/redis/RedisConfig.java diff --git a/src/main/java/com/asap/server/config/redis/RedisConfig.java b/src/main/java/com/asap/server/config/redis/RedisConfig.java new file mode 100644 index 00000000..d3f8c2c7 --- /dev/null +++ b/src/main/java/com/asap/server/config/redis/RedisConfig.java @@ -0,0 +1,25 @@ +package com.asap.server.config.redis; + +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; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class RedisConfig { + @Value("${spring.data.redis.host}") + private String redisHost; + @Value("${spring.data.redis.port}") + private int redisPort; + private static final String REDISSON_HOST_PREFIX = "redis://"; + + @Bean + RedissonClient getRedissonClient() { + Config config = new Config(); + config.useSingleServer() + .setAddress(REDISSON_HOST_PREFIX + redisHost + ":" + redisPort); + return Redisson.create(config); + } +} From 4a10253b7bee827e96bd137e6aebc463b30e5855 Mon Sep 17 00:00:00 2001 From: KWY Date: Wed, 8 May 2024 23:05:27 +0900 Subject: [PATCH 03/50] =?UTF-8?q?#259=20[del]=20filter=20=EB=82=B4=20compo?= =?UTF-8?q?nent=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/filter/CustomServletWrappingFilter.java | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/asap/server/common/filter/CustomServletWrappingFilter.java b/src/main/java/com/asap/server/common/filter/CustomServletWrappingFilter.java index 4fa9a358..9c2b21dc 100644 --- a/src/main/java/com/asap/server/common/filter/CustomServletWrappingFilter.java +++ b/src/main/java/com/asap/server/common/filter/CustomServletWrappingFilter.java @@ -1,17 +1,15 @@ package com.asap.server.common.filter; -import org.springframework.stereotype.Component; -import org.springframework.web.filter.OncePerRequestFilter; -import org.springframework.web.util.ContentCachingRequestWrapper; -import org.springframework.web.util.ContentCachingResponseWrapper; - import jakarta.servlet.FilterChain; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; +import org.springframework.web.filter.OncePerRequestFilter; +import org.springframework.web.util.ContentCachingRequestWrapper; +import org.springframework.web.util.ContentCachingResponseWrapper; + import java.io.IOException; -@Component public class CustomServletWrappingFilter extends OncePerRequestFilter { @Override protected void doFilterInternal(final HttpServletRequest request, From 8052a7a8711f505667c963d599c4266436e36f56 Mon Sep 17 00:00:00 2001 From: sohyundoh Date: Wed, 8 May 2024 23:38:08 +0900 Subject: [PATCH 04/50] =?UTF-8?q?#259=20[feat]=20duplicated=20interceptor?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../interceptor/DuplicatedInterceptor.java | 49 +++++++++++++++++++ .../com/asap/server/config/WebConfig.java | 9 ++++ 2 files changed, 58 insertions(+) create mode 100644 src/main/java/com/asap/server/common/interceptor/DuplicatedInterceptor.java diff --git a/src/main/java/com/asap/server/common/interceptor/DuplicatedInterceptor.java b/src/main/java/com/asap/server/common/interceptor/DuplicatedInterceptor.java new file mode 100644 index 00000000..2d639995 --- /dev/null +++ b/src/main/java/com/asap/server/common/interceptor/DuplicatedInterceptor.java @@ -0,0 +1,49 @@ +package com.asap.server.common.interceptor; + + +import com.asap.server.exception.Error; +import com.asap.server.exception.model.InternalErrorException; +import com.asap.server.exception.model.TooManyRequestException; +import com.fasterxml.jackson.databind.ObjectMapper; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import lombok.RequiredArgsConstructor; +import org.redisson.api.RLock; +import org.redisson.api.RedissonClient; +import org.springframework.stereotype.Component; +import org.springframework.web.servlet.HandlerInterceptor; +import org.springframework.web.util.ContentCachingRequestWrapper; + +import java.io.IOException; +import java.util.concurrent.TimeUnit; + +@Component +@RequiredArgsConstructor +public class DuplicatedInterceptor implements HandlerInterceptor { + + private final RedissonClient redissonClient; + private final ObjectMapper objectMapper = new ObjectMapper(); + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException { + final ContentCachingRequestWrapper cachingRequest = (ContentCachingRequestWrapper) request; + final String lockKey = (cachingRequest.getHeader("Host") + objectMapper.readTree(cachingRequest.getContentAsByteArray())); + RLock lock = redissonClient.getLock(lockKey); + boolean isLock = false; + try { + isLock = lock.tryLock(0, 0, TimeUnit.SECONDS); + if (!isLock) throw new TooManyRequestException(Error.TOO_MANY_REQUEST_EXCEPTION); + } catch (InterruptedException e) { + throw new InternalErrorException(Error.INTERNAL_SERVER_ERROR); + } + return true; + } + + @Override + public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { + final ContentCachingRequestWrapper cachingRequest = (ContentCachingRequestWrapper) request; + final String lockKey = (cachingRequest.getHeader("Host") + objectMapper.readTree(cachingRequest.getContentAsByteArray())); + RLock lock = redissonClient.getLock(lockKey); + lock.unlock(); + } +} diff --git a/src/main/java/com/asap/server/config/WebConfig.java b/src/main/java/com/asap/server/config/WebConfig.java index 5d3a3b9b..32b70cbd 100644 --- a/src/main/java/com/asap/server/config/WebConfig.java +++ b/src/main/java/com/asap/server/config/WebConfig.java @@ -1,5 +1,6 @@ package com.asap.server.config; +import com.asap.server.common.interceptor.DuplicatedInterceptor; import com.asap.server.config.resolver.meeting.MeetingPathVariableResolver; import com.asap.server.config.resolver.user.UserIdResolver; import lombok.RequiredArgsConstructor; @@ -9,6 +10,7 @@ import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.web.method.support.HandlerMethodArgumentResolver; import org.springframework.web.servlet.config.annotation.CorsRegistry; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import java.util.List; @@ -18,6 +20,7 @@ public class WebConfig implements WebMvcConfigurer { private final UserIdResolver userIdResolver; private final MeetingPathVariableResolver meetingPathVariableResolver; + private final DuplicatedInterceptor duplicatedInterceptor; @Bean public PasswordEncoder getPasswordEncoder() { @@ -37,4 +40,10 @@ public void addArgumentResolvers(List resolvers) resolvers.add(userIdResolver); resolvers.add(meetingPathVariableResolver); } + + @Override + public void addInterceptors(InterceptorRegistry interceptorRegistry) { + interceptorRegistry.addInterceptor(duplicatedInterceptor) + .addPathPatterns("/meeting", "/user/{meetingId}/time", "user/host/{meetingId}/time"); + } } From 6c88c737860e7b793788d41adaed24b424e88e73 Mon Sep 17 00:00:00 2001 From: sohyundoh Date: Wed, 8 May 2024 23:38:42 +0900 Subject: [PATCH 05/50] =?UTF-8?q?#259=20[feat]=20=EC=98=88=EC=99=B8=20?= =?UTF-8?q?=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/advice/ControllerExceptionAdvice.java | 15 ++++++++++++--- .../java/com/asap/server/exception/Error.java | 4 ++++ .../exception/model/InternalErrorException.java | 9 +++++++++ .../exception/model/TooManyRequestException.java | 10 ++++++++++ 4 files changed, 35 insertions(+), 3 deletions(-) create mode 100644 src/main/java/com/asap/server/exception/model/InternalErrorException.java create mode 100644 src/main/java/com/asap/server/exception/model/TooManyRequestException.java diff --git a/src/main/java/com/asap/server/common/advice/ControllerExceptionAdvice.java b/src/main/java/com/asap/server/common/advice/ControllerExceptionAdvice.java index 0b82892c..48c92a74 100644 --- a/src/main/java/com/asap/server/common/advice/ControllerExceptionAdvice.java +++ b/src/main/java/com/asap/server/common/advice/ControllerExceptionAdvice.java @@ -10,8 +10,12 @@ import com.asap.server.exception.model.ConflictException; import com.asap.server.exception.model.ForbiddenException; import com.asap.server.exception.model.HostTimeForbiddenException; +import com.asap.server.exception.model.InternalErrorException; import com.asap.server.exception.model.NotFoundException; import com.asap.server.exception.model.UnauthorizedException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.validation.ConstraintViolationException; +import jakarta.validation.ValidationException; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpStatus; @@ -24,9 +28,6 @@ import org.springframework.web.bind.annotation.RestControllerAdvice; import org.springframework.web.servlet.NoHandlerFoundException; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.validation.ConstraintViolationException; -import jakarta.validation.ValidationException; import java.io.IOException; import static com.asap.server.exception.Error.METHOD_NOT_ALLOWED_EXCEPTION; @@ -133,9 +134,17 @@ protected ErrorResponse handleConflictException(final ConflictException e) { return ErrorResponse.error(e.getError()); } + /** * 500 Internal Server */ + + @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) + @ExceptionHandler(InternalErrorException.class) + protected ErrorResponse handleInternalErrorException(final InternalErrorException e) { + return ErrorResponse.error(e.getError()); + } + @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) @ExceptionHandler(Exception.class) protected ErrorResponse handleException(final Exception error, final HttpServletRequest request) throws IOException { diff --git a/src/main/java/com/asap/server/exception/Error.java b/src/main/java/com/asap/server/exception/Error.java index 971754ce..b3d28e67 100644 --- a/src/main/java/com/asap/server/exception/Error.java +++ b/src/main/java/com/asap/server/exception/Error.java @@ -53,6 +53,10 @@ public enum Error { */ MEETING_VALIDATION_FAILED_EXCEPTION(HttpStatus.CONFLICT, "이미 확정된 회의입니다."), HOST_TIME_EXIST_EXCEPTION(HttpStatus.CONFLICT, "이미 방장의 회의 가능시간이 이미 존재합니다."), + /* + * 429 TOO MANY REQUEST + */ + TOO_MANY_REQUEST_EXCEPTION(HttpStatus.TOO_MANY_REQUESTS, "중복된 요청입니다."), /** * 500 INTERNAL SERVER ERROR */ diff --git a/src/main/java/com/asap/server/exception/model/InternalErrorException.java b/src/main/java/com/asap/server/exception/model/InternalErrorException.java new file mode 100644 index 00000000..130349c9 --- /dev/null +++ b/src/main/java/com/asap/server/exception/model/InternalErrorException.java @@ -0,0 +1,9 @@ +package com.asap.server.exception.model; + +import com.asap.server.exception.Error; + +public class InternalErrorException extends AsapException { + public InternalErrorException(final Error error) { + super(error); + } +} diff --git a/src/main/java/com/asap/server/exception/model/TooManyRequestException.java b/src/main/java/com/asap/server/exception/model/TooManyRequestException.java new file mode 100644 index 00000000..6ada2dba --- /dev/null +++ b/src/main/java/com/asap/server/exception/model/TooManyRequestException.java @@ -0,0 +1,10 @@ +package com.asap.server.exception.model; + +import com.asap.server.exception.Error; + +public class TooManyRequestException extends AsapException { + + public TooManyRequestException(final Error error) { + super(error); + } +} From 894c0860dfbc17c006aea0d4f2137ed10feb8b54 Mon Sep 17 00:00:00 2001 From: KWY Date: Thu, 9 May 2024 00:42:45 +0900 Subject: [PATCH 06/50] =?UTF-8?q?#259=20[fix]=20end=20point=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 --- src/main/java/com/asap/server/config/WebConfig.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/asap/server/config/WebConfig.java b/src/main/java/com/asap/server/config/WebConfig.java index 32b70cbd..42143da7 100644 --- a/src/main/java/com/asap/server/config/WebConfig.java +++ b/src/main/java/com/asap/server/config/WebConfig.java @@ -44,6 +44,6 @@ public void addArgumentResolvers(List resolvers) @Override public void addInterceptors(InterceptorRegistry interceptorRegistry) { interceptorRegistry.addInterceptor(duplicatedInterceptor) - .addPathPatterns("/meeting", "/user/{meetingId}/time", "user/host/{meetingId}/time"); + .addPathPatterns("/meeting", "/user/{meetingId}/time", "/user/host/{meetingId}/time"); } } From d810526bb18a09d1028458e013fad578ce99be97 Mon Sep 17 00:00:00 2001 From: KWY Date: Thu, 9 May 2024 00:44:28 +0900 Subject: [PATCH 07/50] =?UTF-8?q?#259=20[feat]=20request=20wrapping=20?= =?UTF-8?q?=EB=B0=A9=EC=8B=9D=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../server/common/aspect/LoggingAspect.java | 13 ++-- .../CustomHttpServletRequestWrapper.java | 61 +++++++++++++++++++ .../filter/CustomServletWrappingFilter.java | 22 +++---- 3 files changed, 73 insertions(+), 23 deletions(-) create mode 100644 src/main/java/com/asap/server/common/filter/CustomHttpServletRequestWrapper.java diff --git a/src/main/java/com/asap/server/common/aspect/LoggingAspect.java b/src/main/java/com/asap/server/common/aspect/LoggingAspect.java index f944265d..9556594b 100644 --- a/src/main/java/com/asap/server/common/aspect/LoggingAspect.java +++ b/src/main/java/com/asap/server/common/aspect/LoggingAspect.java @@ -1,6 +1,7 @@ package com.asap.server.common.aspect; -import com.fasterxml.jackson.databind.ObjectMapper; +import com.asap.server.common.filter.CustomHttpServletRequestWrapper; +import jakarta.servlet.http.HttpServletRequest; import lombok.extern.slf4j.Slf4j; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; @@ -9,9 +10,7 @@ import org.springframework.stereotype.Component; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; -import org.springframework.web.util.ContentCachingRequestWrapper; -import jakarta.servlet.http.HttpServletRequest; import java.util.Enumeration; import java.util.HashMap; import java.util.Map; @@ -21,8 +20,6 @@ @Slf4j public class LoggingAspect { - private final ObjectMapper objectMapper = new ObjectMapper(); - @Pointcut("execution(* com.asap.server.controller..*(..)) || ( execution(* com.asap.server.common.advice..*(..)) && !execution(* com.asap.server.common.advice.ControllerExceptionAdvice.handleException*(..)))") public void controllerInfoLevelExecute() { } @@ -34,7 +31,6 @@ public void controllerErrorLevelExecute() { @Around("com.asap.server.common.aspect.LoggingAspect.controllerInfoLevelExecute()") public Object requestInfoLevelLogging(ProceedingJoinPoint proceedingJoinPoint) throws Throwable { HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest(); - final ContentCachingRequestWrapper cachingRequest = (ContentCachingRequestWrapper) request; long startAt = System.currentTimeMillis(); Object returnValue = proceedingJoinPoint.proceed(proceedingJoinPoint.getArgs()); long endAt = System.currentTimeMillis(); @@ -42,7 +38,7 @@ public Object requestInfoLevelLogging(ProceedingJoinPoint proceedingJoinPoint) t log.info("================================================NEW==============================================="); log.info("====> Request: {} {} ({}ms)\n *Header = {}", request.getMethod(), request.getRequestURL(), endAt - startAt, getHeaders(request)); if ("POST".equalsIgnoreCase(request.getMethod())) { - log.info("====> Body: {}", objectMapper.readTree(cachingRequest.getContentAsByteArray())); + log.info("====> Body: {}", ((CustomHttpServletRequestWrapper) request).getBody()); } if (returnValue != null) { log.info("====> Response: {}", returnValue); @@ -54,14 +50,13 @@ public Object requestInfoLevelLogging(ProceedingJoinPoint proceedingJoinPoint) t @Around("com.asap.server.common.aspect.LoggingAspect.controllerErrorLevelExecute()") public Object requestErrorLevelLogging(ProceedingJoinPoint proceedingJoinPoint) throws Throwable { HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest(); - final ContentCachingRequestWrapper cachingRequest = (ContentCachingRequestWrapper) request; long startAt = System.currentTimeMillis(); Object returnValue = proceedingJoinPoint.proceed(proceedingJoinPoint.getArgs()); long endAt = System.currentTimeMillis(); log.error("====> Request: {} {} ({}ms)\n *Header = {}", request.getMethod(), request.getRequestURL(), endAt - startAt, getHeaders(request)); if ("POST".equalsIgnoreCase(request.getMethod())) { - log.error("====> Body: {}", objectMapper.readTree(cachingRequest.getContentAsByteArray())); + log.error("====> Body: {}", ((CustomHttpServletRequestWrapper) request).getBody()); } if (returnValue != null) { log.error("====> Response: {}", returnValue); diff --git a/src/main/java/com/asap/server/common/filter/CustomHttpServletRequestWrapper.java b/src/main/java/com/asap/server/common/filter/CustomHttpServletRequestWrapper.java new file mode 100644 index 00000000..5cd33593 --- /dev/null +++ b/src/main/java/com/asap/server/common/filter/CustomHttpServletRequestWrapper.java @@ -0,0 +1,61 @@ +package com.asap.server.common.filter; + +import jakarta.servlet.ReadListener; +import jakarta.servlet.ServletInputStream; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequestWrapper; +import lombok.Getter; + +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; + +@Getter +public class CustomHttpServletRequestWrapper extends HttpServletRequestWrapper { + private final String body; + + public CustomHttpServletRequestWrapper(HttpServletRequest request) throws IOException { + super(request); + this.body = readBody(request); + } + + @Override + public ServletInputStream getInputStream() { + ByteArrayInputStream byteInputStream = new ByteArrayInputStream(body.getBytes(StandardCharsets.UTF_8)); + return new ServletInputStream() { + @Override + public boolean isFinished() { + return false; + } + + @Override + public boolean isReady() { + return false; + } + + @Override + public void setReadListener(ReadListener readListener) { + + } + + @Override + public int read() throws IOException { + return byteInputStream.read(); + } + }; + } + + private String readBody(HttpServletRequest request) throws IOException { + BufferedReader input = new BufferedReader(new InputStreamReader(request.getInputStream())); + StringBuilder sb = new StringBuilder(); + + var line = input.readLine(); + while (line != null) { + sb.append(line.trim()); + line = input.readLine(); + } + return sb.toString(); + } +} diff --git a/src/main/java/com/asap/server/common/filter/CustomServletWrappingFilter.java b/src/main/java/com/asap/server/common/filter/CustomServletWrappingFilter.java index 9c2b21dc..9bf7cea3 100644 --- a/src/main/java/com/asap/server/common/filter/CustomServletWrappingFilter.java +++ b/src/main/java/com/asap/server/common/filter/CustomServletWrappingFilter.java @@ -1,25 +1,19 @@ package com.asap.server.common.filter; +import jakarta.servlet.Filter; import jakarta.servlet.FilterChain; import jakarta.servlet.ServletException; +import jakarta.servlet.ServletRequest; +import jakarta.servlet.ServletResponse; import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import org.springframework.web.filter.OncePerRequestFilter; -import org.springframework.web.util.ContentCachingRequestWrapper; -import org.springframework.web.util.ContentCachingResponseWrapper; import java.io.IOException; -public class CustomServletWrappingFilter extends OncePerRequestFilter { - @Override - protected void doFilterInternal(final HttpServletRequest request, - final HttpServletResponse response, - final FilterChain chain) throws ServletException, IOException { - ContentCachingRequestWrapper requestWrapper = new ContentCachingRequestWrapper(request); - ContentCachingResponseWrapper responseWrapper = new ContentCachingResponseWrapper(response); - - chain.doFilter(requestWrapper, responseWrapper); +public class CustomServletWrappingFilter implements Filter { - responseWrapper.copyBodyToResponse(); + @Override + public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { + HttpServletRequest request = new CustomHttpServletRequestWrapper((HttpServletRequest) servletRequest); + filterChain.doFilter(request, servletResponse); } } From 3702ca35d77996610fdf523b50e60af0d648ae6f Mon Sep 17 00:00:00 2001 From: KWY Date: Thu, 9 May 2024 00:44:48 +0900 Subject: [PATCH 08/50] =?UTF-8?q?#259=20[feat]=20interceptor=20lock=20?= =?UTF-8?q?=EB=B0=A9=EC=8B=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../interceptor/DuplicatedInterceptor.java | 53 ++++++++++--------- 1 file changed, 28 insertions(+), 25 deletions(-) diff --git a/src/main/java/com/asap/server/common/interceptor/DuplicatedInterceptor.java b/src/main/java/com/asap/server/common/interceptor/DuplicatedInterceptor.java index 2d639995..61b9c774 100644 --- a/src/main/java/com/asap/server/common/interceptor/DuplicatedInterceptor.java +++ b/src/main/java/com/asap/server/common/interceptor/DuplicatedInterceptor.java @@ -1,49 +1,52 @@ package com.asap.server.common.interceptor; +import com.asap.server.common.filter.CustomHttpServletRequestWrapper; import com.asap.server.exception.Error; -import com.asap.server.exception.model.InternalErrorException; import com.asap.server.exception.model.TooManyRequestException; -import com.fasterxml.jackson.databind.ObjectMapper; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; -import org.redisson.api.RLock; +import org.redisson.api.RMap; import org.redisson.api.RedissonClient; import org.springframework.stereotype.Component; import org.springframework.web.servlet.HandlerInterceptor; -import org.springframework.web.util.ContentCachingRequestWrapper; - -import java.io.IOException; -import java.util.concurrent.TimeUnit; +import org.springframework.web.servlet.ModelAndView; @Component @RequiredArgsConstructor public class DuplicatedInterceptor implements HandlerInterceptor { - + private static final String REDIS_KEY = "ASAP_REDIS"; + private static final String RMAP_VALUE = "ASAP"; private final RedissonClient redissonClient; - private final ObjectMapper objectMapper = new ObjectMapper(); @Override - public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException { - final ContentCachingRequestWrapper cachingRequest = (ContentCachingRequestWrapper) request; - final String lockKey = (cachingRequest.getHeader("Host") + objectMapper.readTree(cachingRequest.getContentAsByteArray())); - RLock lock = redissonClient.getLock(lockKey); - boolean isLock = false; - try { - isLock = lock.tryLock(0, 0, TimeUnit.SECONDS); - if (!isLock) throw new TooManyRequestException(Error.TOO_MANY_REQUEST_EXCEPTION); - } catch (InterruptedException e) { - throw new InternalErrorException(Error.INTERNAL_SERVER_ERROR); - } - return true; + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { + if (lock(request)) return true; + throw new TooManyRequestException(Error.TOO_MANY_REQUEST_EXCEPTION); + } + + @Override + public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { + unLock(request); + HandlerInterceptor.super.postHandle(request, response, handler, modelAndView); } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { - final ContentCachingRequestWrapper cachingRequest = (ContentCachingRequestWrapper) request; - final String lockKey = (cachingRequest.getHeader("Host") + objectMapper.readTree(cachingRequest.getContentAsByteArray())); - RLock lock = redissonClient.getLock(lockKey); - lock.unlock(); + unLock(request); + HandlerInterceptor.super.afterCompletion(request, response, handler, ex); + } + + private boolean lock(HttpServletRequest request) { + final String rmapKey = ((CustomHttpServletRequestWrapper) request).getBody(); + RMap redissonClientMap = redissonClient.getMap(REDIS_KEY); + return redissonClientMap.putIfAbsent(rmapKey, RMAP_VALUE) == null; + } + + private void unLock(HttpServletRequest request) { + final String rmapKey = ((CustomHttpServletRequestWrapper) request).getBody(); + RMap redissonClientMap = redissonClient.getMap(REDIS_KEY); + redissonClientMap.remove(rmapKey); } } From 96556e8bc9b88327a5f7af949bf5754af95a8c45 Mon Sep 17 00:00:00 2001 From: sohyundoh Date: Thu, 9 May 2024 09:33:04 +0900 Subject: [PATCH 09/50] =?UTF-8?q?#259=20[feat]=20too=20many=20request=20?= =?UTF-8?q?=EC=98=88=EC=99=B8=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../server/common/advice/ControllerExceptionAdvice.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/main/java/com/asap/server/common/advice/ControllerExceptionAdvice.java b/src/main/java/com/asap/server/common/advice/ControllerExceptionAdvice.java index 48c92a74..47cabbaf 100644 --- a/src/main/java/com/asap/server/common/advice/ControllerExceptionAdvice.java +++ b/src/main/java/com/asap/server/common/advice/ControllerExceptionAdvice.java @@ -12,6 +12,7 @@ import com.asap.server.exception.model.HostTimeForbiddenException; import com.asap.server.exception.model.InternalErrorException; import com.asap.server.exception.model.NotFoundException; +import com.asap.server.exception.model.TooManyRequestException; import com.asap.server.exception.model.UnauthorizedException; import jakarta.servlet.http.HttpServletRequest; import jakarta.validation.ConstraintViolationException; @@ -134,6 +135,14 @@ protected ErrorResponse handleConflictException(final ConflictException e) { return ErrorResponse.error(e.getError()); } + /* + * 429 Too Many Requests + */ + @ResponseStatus(HttpStatus.TOO_MANY_REQUESTS) + @ExceptionHandler(TooManyRequestException.class) + protected ErrorResponse handleTooManyConflictException(final TooManyRequestException e) { + return ErrorResponse.error(e.getError()); + } /** * 500 Internal Server From 718889ebb2a799795bf2c18d1fda066c2abd9614 Mon Sep 17 00:00:00 2001 From: KWY Date: Thu, 9 May 2024 10:50:18 +0900 Subject: [PATCH 10/50] =?UTF-8?q?#259=20[feat]=20=EC=84=A4=EC=A0=95=20?= =?UTF-8?q?=ED=8C=8C=EC=9D=BC=20gitignore=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 6e67e01a..f28df1c2 100644 --- a/.gitignore +++ b/.gitignore @@ -34,4 +34,6 @@ output/ *.log *.log.gz *.log-*.gz -logs/ \ No newline at end of file +logs/ + +/src/main/resources/application.yml \ No newline at end of file From 0ed1ec46ed855d707c2f743e1203351b5d504f5a Mon Sep 17 00:00:00 2001 From: KWY Date: Thu, 9 May 2024 11:08:27 +0900 Subject: [PATCH 11/50] =?UTF-8?q?#259=20[fix]=20profile=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/dev-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dev-ci.yml b/.github/workflows/dev-ci.yml index 50c74852..469d7355 100644 --- a/.github/workflows/dev-ci.yml +++ b/.github/workflows/dev-ci.yml @@ -57,4 +57,4 @@ jobs: run: chmod +x gradlew - name: Build with Gradle # 실제 application build - run: ./gradlew build -PactiveProfiles=local + run: ./gradlew build From 032326df35c61effc2fbd56a9010502398dca933 Mon Sep 17 00:00:00 2001 From: KWY Date: Thu, 9 May 2024 11:14:13 +0900 Subject: [PATCH 12/50] =?UTF-8?q?#259=20[fix]=20market=20place=20mysql=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/dev-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dev-ci.yml b/.github/workflows/dev-ci.yml index 469d7355..641b0b7b 100644 --- a/.github/workflows/dev-ci.yml +++ b/.github/workflows/dev-ci.yml @@ -21,7 +21,7 @@ jobs: steps: - name: Setup MySQL - uses: samin/mysql-action@v1 + uses: mirromutth/mysql-action@v1.1 with: character set server: 'utf8' mysql database: 'asap_dev' From 16622035cb97009abdced7d1ed87dff120360275 Mon Sep 17 00:00:00 2001 From: KWY Date: Thu, 9 May 2024 11:31:24 +0900 Subject: [PATCH 13/50] =?UTF-8?q?#259=20[fix]=20secrets=20=EB=B3=80?= =?UTF-8?q?=EC=88=98=EB=AA=85=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/dev-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dev-ci.yml b/.github/workflows/dev-ci.yml index 641b0b7b..ebdf9cd1 100644 --- a/.github/workflows/dev-ci.yml +++ b/.github/workflows/dev-ci.yml @@ -26,7 +26,7 @@ jobs: character set server: 'utf8' mysql database: 'asap_dev' mysql user: 'asap_dev_admin' - mysql password: ${{ secrets.DatabasePassword }} + mysql password: ${{ secrets.DATABASEPASSWORD }} - uses: actions/checkout@v3 - name: Set up JDK 17 From ab630536687e8ca8e8ad4fc7baf0e38372f1282e Mon Sep 17 00:00:00 2001 From: KWY Date: Thu, 9 May 2024 12:39:25 +0900 Subject: [PATCH 14/50] =?UTF-8?q?#259=20[feat]=20build=EC=8B=9C=20test=20?= =?UTF-8?q?=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/dev-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dev-ci.yml b/.github/workflows/dev-ci.yml index ebdf9cd1..ecd3f55f 100644 --- a/.github/workflows/dev-ci.yml +++ b/.github/workflows/dev-ci.yml @@ -57,4 +57,4 @@ jobs: run: chmod +x gradlew - name: Build with Gradle # 실제 application build - run: ./gradlew build + run: ./gradlew build -x test From 1020e8dc30e842cacf4081d3bc4eef8e9c658765 Mon Sep 17 00:00:00 2001 From: KWY Date: Thu, 9 May 2024 12:41:12 +0900 Subject: [PATCH 15/50] =?UTF-8?q?#259=20[feat]=20build=20=EC=8B=9C=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/dev-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dev-ci.yml b/.github/workflows/dev-ci.yml index ecd3f55f..ebdf9cd1 100644 --- a/.github/workflows/dev-ci.yml +++ b/.github/workflows/dev-ci.yml @@ -57,4 +57,4 @@ jobs: run: chmod +x gradlew - name: Build with Gradle # 실제 application build - run: ./gradlew build -x test + run: ./gradlew build From 5bbdf51436a75b2131382d5ef8b099d632558693 Mon Sep 17 00:00:00 2001 From: KWY Date: Thu, 9 May 2024 12:53:55 +0900 Subject: [PATCH 16/50] =?UTF-8?q?#259=20[fix]=20yaml=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/dev-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dev-ci.yml b/.github/workflows/dev-ci.yml index ebdf9cd1..50a808c4 100644 --- a/.github/workflows/dev-ci.yml +++ b/.github/workflows/dev-ci.yml @@ -26,7 +26,7 @@ jobs: character set server: 'utf8' mysql database: 'asap_dev' mysql user: 'asap_dev_admin' - mysql password: ${{ secrets.DATABASEPASSWORD }} + mysql password: 'asappossible' - uses: actions/checkout@v3 - name: Set up JDK 17 From e20ec9f6f027b77bb82738cb61c167ef592e0ff3 Mon Sep 17 00:00:00 2001 From: KWY Date: Thu, 9 May 2024 12:58:30 +0900 Subject: [PATCH 17/50] 259 [ci] edit db name --- .github/workflows/dev-ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/dev-ci.yml b/.github/workflows/dev-ci.yml index 50a808c4..b4c53e09 100644 --- a/.github/workflows/dev-ci.yml +++ b/.github/workflows/dev-ci.yml @@ -24,9 +24,9 @@ jobs: uses: mirromutth/mysql-action@v1.1 with: character set server: 'utf8' - mysql database: 'asap_dev' - mysql user: 'asap_dev_admin' - mysql password: 'asappossible' + mysql database: 'asap' + mysql user: 'asap' + mysql password: ${{ secrets.DATABASEPASSWORD }} - uses: actions/checkout@v3 - name: Set up JDK 17 From b2848019560a1411b52c5daa3859a489aa9aafe4 Mon Sep 17 00:00:00 2001 From: KWY Date: Thu, 9 May 2024 13:09:12 +0900 Subject: [PATCH 18/50] #259 [ci] check yml --- .github/workflows/dev-ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/dev-ci.yml b/.github/workflows/dev-ci.yml index b4c53e09..9799aee8 100644 --- a/.github/workflows/dev-ci.yml +++ b/.github/workflows/dev-ci.yml @@ -50,6 +50,7 @@ jobs: # application.yml 파일 확인 cat ./application.yml + echo ./application.yml shell: bash # 이 워크플로우는 gradle build From f063385dbf956bc085d8c9555052ee3a9371d2dc Mon Sep 17 00:00:00 2001 From: KWY Date: Thu, 9 May 2024 13:11:31 +0900 Subject: [PATCH 19/50] #259 [ci] read secret --- .github/workflows/dev-ci.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/dev-ci.yml b/.github/workflows/dev-ci.yml index 9799aee8..1c92adbb 100644 --- a/.github/workflows/dev-ci.yml +++ b/.github/workflows/dev-ci.yml @@ -50,7 +50,8 @@ jobs: # application.yml 파일 확인 cat ./application.yml - echo ./application.yml + echo ${{ secrets.DEV_APPLICATION_YAML }} + echo ${{ secrets.DATABASEPASSWORD }} shell: bash # 이 워크플로우는 gradle build From 715479670b50c31265b49f7068ac6396f88ae34b Mon Sep 17 00:00:00 2001 From: KWY Date: Thu, 9 May 2024 13:15:29 +0900 Subject: [PATCH 20/50] #259 [ci] read yaml --- .github/workflows/dev-ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/dev-ci.yml b/.github/workflows/dev-ci.yml index 1c92adbb..fc08abdd 100644 --- a/.github/workflows/dev-ci.yml +++ b/.github/workflows/dev-ci.yml @@ -50,8 +50,8 @@ jobs: # application.yml 파일 확인 cat ./application.yml - echo ${{ secrets.DEV_APPLICATION_YAML }} - echo ${{ secrets.DATABASEPASSWORD }} + cat ${{ secrets.DATABASEPASSWORD }} + cat ${{ secrets.DEV_APPLICATION_YAML }} shell: bash # 이 워크플로우는 gradle build From 647f8136e3abf4913f733ea336512d14d64aeb6b Mon Sep 17 00:00:00 2001 From: KWY Date: Thu, 9 May 2024 13:17:30 +0900 Subject: [PATCH 21/50] #259 [ci] read yaml --- .github/workflows/dev-ci.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/dev-ci.yml b/.github/workflows/dev-ci.yml index fc08abdd..fa561ebf 100644 --- a/.github/workflows/dev-ci.yml +++ b/.github/workflows/dev-ci.yml @@ -50,8 +50,9 @@ jobs: # application.yml 파일 확인 cat ./application.yml + cat "${{ secrets.DATABASEPASSWORD }}" cat ${{ secrets.DATABASEPASSWORD }} - cat ${{ secrets.DEV_APPLICATION_YAML }} + cat "${{ secrets.DEV_APPLICATION_YAML }}" shell: bash # 이 워크플로우는 gradle build From 6508ad350d8b5a71145d2bd5970e374daeff84ac Mon Sep 17 00:00:00 2001 From: KWY Date: Thu, 9 May 2024 13:34:09 +0900 Subject: [PATCH 22/50] #259 [ci] edit mysql dependency --- .github/workflows/dev-ci.yml | 5 +---- build.gradle | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/.github/workflows/dev-ci.yml b/.github/workflows/dev-ci.yml index fa561ebf..606ce996 100644 --- a/.github/workflows/dev-ci.yml +++ b/.github/workflows/dev-ci.yml @@ -34,7 +34,7 @@ jobs: with: java-version: '17' distribution: 'temurin' - + - name: make application.properties 파일 생성 run: | ## create application.yml @@ -50,9 +50,6 @@ jobs: # application.yml 파일 확인 cat ./application.yml - cat "${{ secrets.DATABASEPASSWORD }}" - cat ${{ secrets.DATABASEPASSWORD }} - cat "${{ secrets.DEV_APPLICATION_YAML }}" shell: bash # 이 워크플로우는 gradle build diff --git a/build.gradle b/build.gradle index 49fb1349..0d8147fa 100644 --- a/build.gradle +++ b/build.gradle @@ -43,7 +43,7 @@ dependencies { // JPA & Database implementation 'org.springframework.boot:spring-boot-starter-data-jpa' - implementation 'mysql:mysql-connector-java:8.0.32' + runtimeOnly 'com.mysql:mysql-connector-j' // SWAGGER implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.3.0' From 27d0d387793e24184e95278605615db8f16f3c98 Mon Sep 17 00:00:00 2001 From: KWY Date: Thu, 9 May 2024 13:38:41 +0900 Subject: [PATCH 23/50] =?UTF-8?q?#259=20[ci]=20dependency=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 --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 0d8147fa..fa571819 100644 --- a/build.gradle +++ b/build.gradle @@ -43,7 +43,7 @@ dependencies { // JPA & Database implementation 'org.springframework.boot:spring-boot-starter-data-jpa' - runtimeOnly 'com.mysql:mysql-connector-j' + implementation 'mysql:mysql-connector-java:8.0.33' // SWAGGER implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.3.0' From 17c581c634dadc45acea2281f0072f6a1b363229 Mon Sep 17 00:00:00 2001 From: KWY Date: Thu, 9 May 2024 13:55:59 +0900 Subject: [PATCH 24/50] #259 [ci] edit echo --- .github/workflows/dev-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dev-ci.yml b/.github/workflows/dev-ci.yml index 606ce996..b920cb5b 100644 --- a/.github/workflows/dev-ci.yml +++ b/.github/workflows/dev-ci.yml @@ -46,7 +46,7 @@ jobs: touch ./application.yml # GitHub-Actions 에서 설정한 값을 application.yml 파일에 쓰기 - echo "${{ secrets.DEV_APPLICATION_YAML }}" >> ./application.yml + echo "${{ secrets.DEV_APPLICATION_YAML }}" > ./application.yml # application.yml 파일 확인 cat ./application.yml From 5b946d63e70051240e064bcd40bb181aa955e095 Mon Sep 17 00:00:00 2001 From: KWY Date: Thu, 9 May 2024 14:12:49 +0900 Subject: [PATCH 25/50] #259 [ci] fix user name --- .github/workflows/dev-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dev-ci.yml b/.github/workflows/dev-ci.yml index b920cb5b..6e10a886 100644 --- a/.github/workflows/dev-ci.yml +++ b/.github/workflows/dev-ci.yml @@ -25,7 +25,7 @@ jobs: with: character set server: 'utf8' mysql database: 'asap' - mysql user: 'asap' + mysql user: 'asapuser' mysql password: ${{ secrets.DATABASEPASSWORD }} - uses: actions/checkout@v3 From 92d45e86141c76aba95a903c693a9680d7cd8cf4 Mon Sep 17 00:00:00 2001 From: KWY Date: Thu, 9 May 2024 14:16:45 +0900 Subject: [PATCH 26/50] #259 [ci] wait mysql --- .github/workflows/dev-ci.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/dev-ci.yml b/.github/workflows/dev-ci.yml index 6e10a886..7f7fecc8 100644 --- a/.github/workflows/dev-ci.yml +++ b/.github/workflows/dev-ci.yml @@ -28,6 +28,9 @@ jobs: mysql user: 'asapuser' mysql password: ${{ secrets.DATABASEPASSWORD }} + - name: Wait for MySQL + run: sleep 15 + - uses: actions/checkout@v3 - name: Set up JDK 17 uses: actions/setup-java@v3 From 8a184a910b6bba786a53b8e0a2fd91921e2486a2 Mon Sep 17 00:00:00 2001 From: KWY Date: Thu, 9 May 2024 14:21:51 +0900 Subject: [PATCH 27/50] #259 [ci] wait mysql --- .github/workflows/dev-ci.yml | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/.github/workflows/dev-ci.yml b/.github/workflows/dev-ci.yml index 7f7fecc8..c34330e3 100644 --- a/.github/workflows/dev-ci.yml +++ b/.github/workflows/dev-ci.yml @@ -16,6 +16,8 @@ permissions: jobs: build: + env: + MYSQL_ROOT_PASSWORD: ${{ secrets.DATABASEPASSWORD }} runs-on: ubuntu-latest @@ -26,10 +28,13 @@ jobs: character set server: 'utf8' mysql database: 'asap' mysql user: 'asapuser' - mysql password: ${{ secrets.DATABASEPASSWORD }} - + mysql password: $MYSQL_ROOT_PASSWORD + - name: Wait for MySQL - run: sleep 15 + run: | + while ! mysqladmin ping --host=127.0.0.1 --password=$MYSQL_ROOT_PASSWORD --silent; do + sleep 1 + done - uses: actions/checkout@v3 - name: Set up JDK 17 From 4604ba2db508162474f117b24452ce79b5da574e Mon Sep 17 00:00:00 2001 From: KWY Date: Thu, 9 May 2024 14:33:07 +0900 Subject: [PATCH 28/50] #259 [ci] add root password --- .github/workflows/dev-ci.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/dev-ci.yml b/.github/workflows/dev-ci.yml index c34330e3..1ed44fc7 100644 --- a/.github/workflows/dev-ci.yml +++ b/.github/workflows/dev-ci.yml @@ -29,6 +29,7 @@ jobs: mysql database: 'asap' mysql user: 'asapuser' mysql password: $MYSQL_ROOT_PASSWORD + mysql root password: $MYSQL_ROOT_PASSWORD - name: Wait for MySQL run: | @@ -59,7 +60,7 @@ jobs: # application.yml 파일 확인 cat ./application.yml shell: bash - + # 이 워크플로우는 gradle build - name: Grant execute permission for gradlew run: chmod +x gradlew From f1a797c7f92a13de7980b2d7644a78ba5fdec7a5 Mon Sep 17 00:00:00 2001 From: KWY Date: Thu, 9 May 2024 14:35:54 +0900 Subject: [PATCH 29/50] #259 [ci] cat mysql password --- .github/workflows/dev-ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/dev-ci.yml b/.github/workflows/dev-ci.yml index 1ed44fc7..b89f2484 100644 --- a/.github/workflows/dev-ci.yml +++ b/.github/workflows/dev-ci.yml @@ -59,6 +59,7 @@ jobs: # application.yml 파일 확인 cat ./application.yml + cat $MYSQL_ROOT_PASSWORD shell: bash # 이 워크플로우는 gradle build From 5d1e6b52cb24a26c6ce5d6caa39a8254a7e49267 Mon Sep 17 00:00:00 2001 From: KWY Date: Thu, 9 May 2024 14:37:43 +0900 Subject: [PATCH 30/50] #259 [ci] change workflow --- .github/workflows/dev-ci.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/dev-ci.yml b/.github/workflows/dev-ci.yml index b89f2484..a2f8425f 100644 --- a/.github/workflows/dev-ci.yml +++ b/.github/workflows/dev-ci.yml @@ -30,12 +30,6 @@ jobs: mysql user: 'asapuser' mysql password: $MYSQL_ROOT_PASSWORD mysql root password: $MYSQL_ROOT_PASSWORD - - - name: Wait for MySQL - run: | - while ! mysqladmin ping --host=127.0.0.1 --password=$MYSQL_ROOT_PASSWORD --silent; do - sleep 1 - done - uses: actions/checkout@v3 - name: Set up JDK 17 @@ -65,6 +59,12 @@ jobs: # 이 워크플로우는 gradle build - name: Grant execute permission for gradlew run: chmod +x gradlew - + + - name: Wait for MySQL + run: | + while ! mysqladmin ping --host=127.0.0.1 --password=$MYSQL_ROOT_PASSWORD --silent; do + sleep 1 + done + - name: Build with Gradle # 실제 application build run: ./gradlew build From ac7638647502497698d4a61dc1047ce1764a91d7 Mon Sep 17 00:00:00 2001 From: KWY Date: Thu, 9 May 2024 14:39:50 +0900 Subject: [PATCH 31/50] #259 [ci] password --- .github/workflows/dev-ci.yml | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/.github/workflows/dev-ci.yml b/.github/workflows/dev-ci.yml index a2f8425f..c9f23a57 100644 --- a/.github/workflows/dev-ci.yml +++ b/.github/workflows/dev-ci.yml @@ -16,9 +16,6 @@ permissions: jobs: build: - env: - MYSQL_ROOT_PASSWORD: ${{ secrets.DATABASEPASSWORD }} - runs-on: ubuntu-latest steps: @@ -28,8 +25,8 @@ jobs: character set server: 'utf8' mysql database: 'asap' mysql user: 'asapuser' - mysql password: $MYSQL_ROOT_PASSWORD - mysql root password: $MYSQL_ROOT_PASSWORD + mysql password: 'asappossible' + mysql root password: 'asappossible' - uses: actions/checkout@v3 - name: Set up JDK 17 @@ -62,9 +59,9 @@ jobs: - name: Wait for MySQL run: | - while ! mysqladmin ping --host=127.0.0.1 --password=$MYSQL_ROOT_PASSWORD --silent; do + while ! mysqladmin ping --host=127.0.0.1 --password='asappossible' --silent; do sleep 1 done - + - name: Build with Gradle # 실제 application build run: ./gradlew build From cc263f3322ac310a70f765062fab866f4b729b6f Mon Sep 17 00:00:00 2001 From: KWY Date: Thu, 9 May 2024 14:46:22 +0900 Subject: [PATCH 32/50] =?UTF-8?q?#259=20[ci]=20user=20=EC=A0=95=EB=B3=B4?= =?UTF-8?q?=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/dev-ci.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/dev-ci.yml b/.github/workflows/dev-ci.yml index c9f23a57..69800fcb 100644 --- a/.github/workflows/dev-ci.yml +++ b/.github/workflows/dev-ci.yml @@ -26,7 +26,6 @@ jobs: mysql database: 'asap' mysql user: 'asapuser' mysql password: 'asappossible' - mysql root password: 'asappossible' - uses: actions/checkout@v3 - name: Set up JDK 17 @@ -50,7 +49,6 @@ jobs: # application.yml 파일 확인 cat ./application.yml - cat $MYSQL_ROOT_PASSWORD shell: bash # 이 워크플로우는 gradle build @@ -59,7 +57,7 @@ jobs: - name: Wait for MySQL run: | - while ! mysqladmin ping --host=127.0.0.1 --password='asappossible' --silent; do + while ! mysqladmin ping --host=127.0.0.1 --user="asapuser" --password="asappossible" --silent; do sleep 1 done From 1d64da45d8577f18ed7d0648d5dfa7a3a7ff0978 Mon Sep 17 00:00:00 2001 From: KWY Date: Thu, 9 May 2024 14:52:03 +0900 Subject: [PATCH 33/50] #259 [ci] admin password --- .github/workflows/dev-ci.yml | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/.github/workflows/dev-ci.yml b/.github/workflows/dev-ci.yml index 69800fcb..3bad8750 100644 --- a/.github/workflows/dev-ci.yml +++ b/.github/workflows/dev-ci.yml @@ -22,10 +22,7 @@ jobs: - name: Setup MySQL uses: mirromutth/mysql-action@v1.1 with: - character set server: 'utf8' - mysql database: 'asap' - mysql user: 'asapuser' - mysql password: 'asappossible' + mysql root password: 'asap' - uses: actions/checkout@v3 - name: Set up JDK 17 @@ -57,7 +54,7 @@ jobs: - name: Wait for MySQL run: | - while ! mysqladmin ping --host=127.0.0.1 --user="asapuser" --password="asappossible" --silent; do + while ! mysqladmin ping --host=127.0.0.1 --password='asap' --silent; do sleep 1 done From bb1a0bd8e4227c3d899d778cfd6f7d4c48c2596b Mon Sep 17 00:00:00 2001 From: KWY Date: Thu, 9 May 2024 14:55:41 +0900 Subject: [PATCH 34/50] #259 [ci] add user --- .github/workflows/dev-ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/dev-ci.yml b/.github/workflows/dev-ci.yml index 3bad8750..13273f9a 100644 --- a/.github/workflows/dev-ci.yml +++ b/.github/workflows/dev-ci.yml @@ -23,6 +23,8 @@ jobs: uses: mirromutth/mysql-action@v1.1 with: mysql root password: 'asap' + mysql user: 'asap' + mysql password: 'asap' - uses: actions/checkout@v3 - name: Set up JDK 17 From b76f3c38f1de38bb1985dabfa2f8f9477d0d0957 Mon Sep 17 00:00:00 2001 From: KWY Date: Thu, 9 May 2024 15:08:45 +0900 Subject: [PATCH 35/50] #259 [ci] character set add --- .github/workflows/dev-ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/dev-ci.yml b/.github/workflows/dev-ci.yml index 13273f9a..8e0fa0f6 100644 --- a/.github/workflows/dev-ci.yml +++ b/.github/workflows/dev-ci.yml @@ -17,15 +17,15 @@ permissions: jobs: build: runs-on: ubuntu-latest - steps: - name: Setup MySQL uses: mirromutth/mysql-action@v1.1 with: + character set server: 'utf8' mysql root password: 'asap' mysql user: 'asap' mysql password: 'asap' - + - uses: actions/checkout@v3 - name: Set up JDK 17 uses: actions/setup-java@v3 From a96d1aa266639cb4be0f86408dda8092b9876fd6 Mon Sep 17 00:00:00 2001 From: KWY Date: Thu, 9 May 2024 15:11:40 +0900 Subject: [PATCH 36/50] #259 [ci] edit marketplace --- .github/workflows/dev-ci.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/dev-ci.yml b/.github/workflows/dev-ci.yml index 8e0fa0f6..1cfdbb4b 100644 --- a/.github/workflows/dev-ci.yml +++ b/.github/workflows/dev-ci.yml @@ -19,9 +19,8 @@ jobs: runs-on: ubuntu-latest steps: - name: Setup MySQL - uses: mirromutth/mysql-action@v1.1 + uses: samin/mysql-action@v1 with: - character set server: 'utf8' mysql root password: 'asap' mysql user: 'asap' mysql password: 'asap' From 918f5621581e5a2210e4d58bff026a1248ab40d0 Mon Sep 17 00:00:00 2001 From: KWY Date: Thu, 9 May 2024 15:40:46 +0900 Subject: [PATCH 37/50] #259 [ci] clean build --- .github/workflows/dev-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dev-ci.yml b/.github/workflows/dev-ci.yml index 1cfdbb4b..958d1b6d 100644 --- a/.github/workflows/dev-ci.yml +++ b/.github/workflows/dev-ci.yml @@ -60,4 +60,4 @@ jobs: done - name: Build with Gradle # 실제 application build - run: ./gradlew build + run: ./gradlew clean build From 3c3f5467027ec77e67f5263cc2c6ff1d838ad2f2 Mon Sep 17 00:00:00 2001 From: KWY Date: Thu, 9 May 2024 15:48:21 +0900 Subject: [PATCH 38/50] =?UTF-8?q?#259=20[chore]=20springboot=20test=20?= =?UTF-8?q?=EC=A3=BC=EC=84=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../meeting/ConfirmMeetingMethodTest.java | 160 +++++++++--------- 1 file changed, 80 insertions(+), 80 deletions(-) diff --git a/src/test/java/com/asap/server/service/meeting/ConfirmMeetingMethodTest.java b/src/test/java/com/asap/server/service/meeting/ConfirmMeetingMethodTest.java index 18b49056..63634e38 100644 --- a/src/test/java/com/asap/server/service/meeting/ConfirmMeetingMethodTest.java +++ b/src/test/java/com/asap/server/service/meeting/ConfirmMeetingMethodTest.java @@ -1,80 +1,80 @@ -package com.asap.server.service.meeting; - -import com.asap.server.controller.dto.request.MeetingConfirmRequestDto; -import com.asap.server.controller.dto.request.UserRequestDto; -import com.asap.server.domain.Meeting; -import com.asap.server.domain.Place; -import com.asap.server.domain.User; -import com.asap.server.domain.enums.Duration; -import com.asap.server.domain.enums.PlaceType; -import com.asap.server.domain.enums.Role; -import com.asap.server.domain.enums.TimeSlot; -import com.asap.server.service.MeetingService; -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 jakarta.persistence.EntityManager; -import jakarta.transaction.Transactional; -import java.util.List; - -import static org.assertj.core.api.AssertionsForClassTypes.assertThat; - -@SpringBootTest -@Transactional -public class ConfirmMeetingMethodTest { - @Autowired - private MeetingService meetingService; - @Autowired - private EntityManager em; - - @Test - @DisplayName("회의 확정시 ConfirmedDateTime 은 Update 된다.") - void setConfirmDateTimeTest() { - // given - final Place place = Place.builder() - .placeType(PlaceType.OFFLINE) - .build(); - final Meeting meeting = Meeting.builder() - .title("회의 테스트") - .password("0000") - .additionalInfo("") - .duration(Duration.HALF) - .place(place) - .build(); - final User user = User.builder() - .meeting(meeting) - .name("강원용") - .role(Role.HOST) - .isFixed(false) - .build(); - meeting.setHost(user); - - em.persist(meeting); - em.persist(user); - em.flush(); - em.clear(); - - final UserRequestDto userDto = UserRequestDto.builder() - .id(user.getId()) - .name(user.getName()) - .build(); - final MeetingConfirmRequestDto body = MeetingConfirmRequestDto.builder() - .month("09") - .day("07") - .dayOfWeek("월") - .startTime(TimeSlot.SLOT_6_00) - .endTime(TimeSlot.SLOT_6_30) - .users(List.of(userDto)) - .build(); - - // when - meetingService.confirmMeeting(body, meeting.getId(), user.getId()); - - // then - final Meeting result = em.find(Meeting.class, meeting.getId()); - assertThat(result.isConfirmedMeeting()).isTrue(); - } - -} +//package com.asap.server.service.meeting; +// +//import com.asap.server.controller.dto.request.MeetingConfirmRequestDto; +//import com.asap.server.controller.dto.request.UserRequestDto; +//import com.asap.server.domain.Meeting; +//import com.asap.server.domain.Place; +//import com.asap.server.domain.User; +//import com.asap.server.domain.enums.Duration; +//import com.asap.server.domain.enums.PlaceType; +//import com.asap.server.domain.enums.Role; +//import com.asap.server.domain.enums.TimeSlot; +//import com.asap.server.service.MeetingService; +//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 jakarta.persistence.EntityManager; +//import jakarta.transaction.Transactional; +//import java.util.List; +// +//import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +// +//@SpringBootTest +//@Transactional +//public class ConfirmMeetingMethodTest { +// @Autowired +// private MeetingService meetingService; +// @Autowired +// private EntityManager em; +// +// @Test +// @DisplayName("회의 확정시 ConfirmedDateTime 은 Update 된다.") +// void setConfirmDateTimeTest() { +// // given +// final Place place = Place.builder() +// .placeType(PlaceType.OFFLINE) +// .build(); +// final Meeting meeting = Meeting.builder() +// .title("회의 테스트") +// .password("0000") +// .additionalInfo("") +// .duration(Duration.HALF) +// .place(place) +// .build(); +// final User user = User.builder() +// .meeting(meeting) +// .name("강원용") +// .role(Role.HOST) +// .isFixed(false) +// .build(); +// meeting.setHost(user); +// +// em.persist(meeting); +// em.persist(user); +// em.flush(); +// em.clear(); +// +// final UserRequestDto userDto = UserRequestDto.builder() +// .id(user.getId()) +// .name(user.getName()) +// .build(); +// final MeetingConfirmRequestDto body = MeetingConfirmRequestDto.builder() +// .month("09") +// .day("07") +// .dayOfWeek("월") +// .startTime(TimeSlot.SLOT_6_00) +// .endTime(TimeSlot.SLOT_6_30) +// .users(List.of(userDto)) +// .build(); +// +// // when +// meetingService.confirmMeeting(body, meeting.getId(), user.getId()); +// +// // then +// final Meeting result = em.find(Meeting.class, meeting.getId()); +// assertThat(result.isConfirmedMeeting()).isTrue(); +// } +// +//} From e42aff58010e940385ae6741f1a58501f18e02c0 Mon Sep 17 00:00:00 2001 From: KWY Date: Thu, 9 May 2024 15:54:35 +0900 Subject: [PATCH 39/50] =?UTF-8?q?#259=20[ci]=20=EC=A3=BC=EC=84=9D=20?= =?UTF-8?q?=ED=95=B4=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../meeting/ConfirmMeetingMethodTest.java | 160 +++++++++--------- 1 file changed, 80 insertions(+), 80 deletions(-) diff --git a/src/test/java/com/asap/server/service/meeting/ConfirmMeetingMethodTest.java b/src/test/java/com/asap/server/service/meeting/ConfirmMeetingMethodTest.java index 63634e38..18b49056 100644 --- a/src/test/java/com/asap/server/service/meeting/ConfirmMeetingMethodTest.java +++ b/src/test/java/com/asap/server/service/meeting/ConfirmMeetingMethodTest.java @@ -1,80 +1,80 @@ -//package com.asap.server.service.meeting; -// -//import com.asap.server.controller.dto.request.MeetingConfirmRequestDto; -//import com.asap.server.controller.dto.request.UserRequestDto; -//import com.asap.server.domain.Meeting; -//import com.asap.server.domain.Place; -//import com.asap.server.domain.User; -//import com.asap.server.domain.enums.Duration; -//import com.asap.server.domain.enums.PlaceType; -//import com.asap.server.domain.enums.Role; -//import com.asap.server.domain.enums.TimeSlot; -//import com.asap.server.service.MeetingService; -//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 jakarta.persistence.EntityManager; -//import jakarta.transaction.Transactional; -//import java.util.List; -// -//import static org.assertj.core.api.AssertionsForClassTypes.assertThat; -// -//@SpringBootTest -//@Transactional -//public class ConfirmMeetingMethodTest { -// @Autowired -// private MeetingService meetingService; -// @Autowired -// private EntityManager em; -// -// @Test -// @DisplayName("회의 확정시 ConfirmedDateTime 은 Update 된다.") -// void setConfirmDateTimeTest() { -// // given -// final Place place = Place.builder() -// .placeType(PlaceType.OFFLINE) -// .build(); -// final Meeting meeting = Meeting.builder() -// .title("회의 테스트") -// .password("0000") -// .additionalInfo("") -// .duration(Duration.HALF) -// .place(place) -// .build(); -// final User user = User.builder() -// .meeting(meeting) -// .name("강원용") -// .role(Role.HOST) -// .isFixed(false) -// .build(); -// meeting.setHost(user); -// -// em.persist(meeting); -// em.persist(user); -// em.flush(); -// em.clear(); -// -// final UserRequestDto userDto = UserRequestDto.builder() -// .id(user.getId()) -// .name(user.getName()) -// .build(); -// final MeetingConfirmRequestDto body = MeetingConfirmRequestDto.builder() -// .month("09") -// .day("07") -// .dayOfWeek("월") -// .startTime(TimeSlot.SLOT_6_00) -// .endTime(TimeSlot.SLOT_6_30) -// .users(List.of(userDto)) -// .build(); -// -// // when -// meetingService.confirmMeeting(body, meeting.getId(), user.getId()); -// -// // then -// final Meeting result = em.find(Meeting.class, meeting.getId()); -// assertThat(result.isConfirmedMeeting()).isTrue(); -// } -// -//} +package com.asap.server.service.meeting; + +import com.asap.server.controller.dto.request.MeetingConfirmRequestDto; +import com.asap.server.controller.dto.request.UserRequestDto; +import com.asap.server.domain.Meeting; +import com.asap.server.domain.Place; +import com.asap.server.domain.User; +import com.asap.server.domain.enums.Duration; +import com.asap.server.domain.enums.PlaceType; +import com.asap.server.domain.enums.Role; +import com.asap.server.domain.enums.TimeSlot; +import com.asap.server.service.MeetingService; +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 jakarta.persistence.EntityManager; +import jakarta.transaction.Transactional; +import java.util.List; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; + +@SpringBootTest +@Transactional +public class ConfirmMeetingMethodTest { + @Autowired + private MeetingService meetingService; + @Autowired + private EntityManager em; + + @Test + @DisplayName("회의 확정시 ConfirmedDateTime 은 Update 된다.") + void setConfirmDateTimeTest() { + // given + final Place place = Place.builder() + .placeType(PlaceType.OFFLINE) + .build(); + final Meeting meeting = Meeting.builder() + .title("회의 테스트") + .password("0000") + .additionalInfo("") + .duration(Duration.HALF) + .place(place) + .build(); + final User user = User.builder() + .meeting(meeting) + .name("강원용") + .role(Role.HOST) + .isFixed(false) + .build(); + meeting.setHost(user); + + em.persist(meeting); + em.persist(user); + em.flush(); + em.clear(); + + final UserRequestDto userDto = UserRequestDto.builder() + .id(user.getId()) + .name(user.getName()) + .build(); + final MeetingConfirmRequestDto body = MeetingConfirmRequestDto.builder() + .month("09") + .day("07") + .dayOfWeek("월") + .startTime(TimeSlot.SLOT_6_00) + .endTime(TimeSlot.SLOT_6_30) + .users(List.of(userDto)) + .build(); + + // when + meetingService.confirmMeeting(body, meeting.getId(), user.getId()); + + // then + final Meeting result = em.find(Meeting.class, meeting.getId()); + assertThat(result.isConfirmedMeeting()).isTrue(); + } + +} From 3259fb1f5700fae38c300c2a4ba282ee527f0f53 Mon Sep 17 00:00:00 2001 From: KWY Date: Thu, 9 May 2024 16:12:55 +0900 Subject: [PATCH 40/50] #259 [ci] del transactional --- .../asap/server/service/meeting/ConfirmMeetingMethodTest.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/test/java/com/asap/server/service/meeting/ConfirmMeetingMethodTest.java b/src/test/java/com/asap/server/service/meeting/ConfirmMeetingMethodTest.java index 18b49056..08002f7e 100644 --- a/src/test/java/com/asap/server/service/meeting/ConfirmMeetingMethodTest.java +++ b/src/test/java/com/asap/server/service/meeting/ConfirmMeetingMethodTest.java @@ -10,19 +10,17 @@ import com.asap.server.domain.enums.Role; import com.asap.server.domain.enums.TimeSlot; import com.asap.server.service.MeetingService; +import jakarta.persistence.EntityManager; 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 jakarta.persistence.EntityManager; -import jakarta.transaction.Transactional; import java.util.List; import static org.assertj.core.api.AssertionsForClassTypes.assertThat; @SpringBootTest -@Transactional public class ConfirmMeetingMethodTest { @Autowired private MeetingService meetingService; From efd665d3b8da01fcfa8169a0d4475525c0b21d72 Mon Sep 17 00:00:00 2001 From: KWY Date: Thu, 9 May 2024 16:16:45 +0900 Subject: [PATCH 41/50] =?UTF-8?q?#259=20[ci]=20springboot=20test=20?= =?UTF-8?q?=EC=A3=BC=EC=84=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../meeting/ConfirmMeetingMethodTest.java | 114 +++++++++--------- 1 file changed, 58 insertions(+), 56 deletions(-) diff --git a/src/test/java/com/asap/server/service/meeting/ConfirmMeetingMethodTest.java b/src/test/java/com/asap/server/service/meeting/ConfirmMeetingMethodTest.java index 08002f7e..75b39ba7 100644 --- a/src/test/java/com/asap/server/service/meeting/ConfirmMeetingMethodTest.java +++ b/src/test/java/com/asap/server/service/meeting/ConfirmMeetingMethodTest.java @@ -11,6 +11,7 @@ import com.asap.server.domain.enums.TimeSlot; import com.asap.server.service.MeetingService; import jakarta.persistence.EntityManager; +import jakarta.transaction.Transactional; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -20,59 +21,60 @@ import static org.assertj.core.api.AssertionsForClassTypes.assertThat; -@SpringBootTest -public class ConfirmMeetingMethodTest { - @Autowired - private MeetingService meetingService; - @Autowired - private EntityManager em; - - @Test - @DisplayName("회의 확정시 ConfirmedDateTime 은 Update 된다.") - void setConfirmDateTimeTest() { - // given - final Place place = Place.builder() - .placeType(PlaceType.OFFLINE) - .build(); - final Meeting meeting = Meeting.builder() - .title("회의 테스트") - .password("0000") - .additionalInfo("") - .duration(Duration.HALF) - .place(place) - .build(); - final User user = User.builder() - .meeting(meeting) - .name("강원용") - .role(Role.HOST) - .isFixed(false) - .build(); - meeting.setHost(user); - - em.persist(meeting); - em.persist(user); - em.flush(); - em.clear(); - - final UserRequestDto userDto = UserRequestDto.builder() - .id(user.getId()) - .name(user.getName()) - .build(); - final MeetingConfirmRequestDto body = MeetingConfirmRequestDto.builder() - .month("09") - .day("07") - .dayOfWeek("월") - .startTime(TimeSlot.SLOT_6_00) - .endTime(TimeSlot.SLOT_6_30) - .users(List.of(userDto)) - .build(); - - // when - meetingService.confirmMeeting(body, meeting.getId(), user.getId()); - - // then - final Meeting result = em.find(Meeting.class, meeting.getId()); - assertThat(result.isConfirmedMeeting()).isTrue(); - } - -} +//@SpringBootTest +//@Transactional +//public class ConfirmMeetingMethodTest { +// @Autowired +// private MeetingService meetingService; +// @Autowired +// private EntityManager em; +// +// @Test +// @DisplayName("회의 확정시 ConfirmedDateTime 은 Update 된다.") +// void setConfirmDateTimeTest() { +// // given +// final Place place = Place.builder() +// .placeType(PlaceType.OFFLINE) +// .build(); +// final Meeting meeting = Meeting.builder() +// .title("회의 테스트") +// .password("0000") +// .additionalInfo("") +// .duration(Duration.HALF) +// .place(place) +// .build(); +// final User user = User.builder() +// .meeting(meeting) +// .name("강원용") +// .role(Role.HOST) +// .isFixed(false) +// .build(); +// meeting.setHost(user); +// +// em.persist(meeting); +// em.persist(user); +// em.flush(); +// em.clear(); +// +// final UserRequestDto userDto = UserRequestDto.builder() +// .id(user.getId()) +// .name(user.getName()) +// .build(); +// final MeetingConfirmRequestDto body = MeetingConfirmRequestDto.builder() +// .month("09") +// .day("07") +// .dayOfWeek("월") +// .startTime(TimeSlot.SLOT_6_00) +// .endTime(TimeSlot.SLOT_6_30) +// .users(List.of(userDto)) +// .build(); +// +// // when +// meetingService.confirmMeeting(body, meeting.getId(), user.getId()); +// +// // then +// final Meeting result = em.find(Meeting.class, meeting.getId()); +// assertThat(result.isConfirmedMeeting()).isTrue(); +// } +// +//} From 10c7eaef5d8aeb6ce3951e2ccbfb8621be3a8e59 Mon Sep 17 00:00:00 2001 From: KWY Date: Mon, 13 May 2024 13:34:00 +0900 Subject: [PATCH 42/50] =?UTF-8?q?#259=20[feat]=20rmap=20key=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=20=ED=95=A8=EC=88=98=20=EC=B6=94=EC=B6=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/interceptor/DuplicatedInterceptor.java | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/asap/server/common/interceptor/DuplicatedInterceptor.java b/src/main/java/com/asap/server/common/interceptor/DuplicatedInterceptor.java index 61b9c774..ef65eb1a 100644 --- a/src/main/java/com/asap/server/common/interceptor/DuplicatedInterceptor.java +++ b/src/main/java/com/asap/server/common/interceptor/DuplicatedInterceptor.java @@ -18,6 +18,8 @@ public class DuplicatedInterceptor implements HandlerInterceptor { private static final String REDIS_KEY = "ASAP_REDIS"; private static final String RMAP_VALUE = "ASAP"; + private static final String RMAP_KEY_FORMAT = "LOCK [ ip : %s , body : %s ]"; + private static final String USER_IP_HEADER = "x-real-ip"; private final RedissonClient redissonClient; @Override @@ -38,14 +40,20 @@ public void afterCompletion(HttpServletRequest request, HttpServletResponse resp HandlerInterceptor.super.afterCompletion(request, response, handler, ex); } + private String getRmapKey(HttpServletRequest request) { + final String body = ((CustomHttpServletRequestWrapper) request).getBody(); + final String userIp = request.getHeader(USER_IP_HEADER); + return String.format(RMAP_KEY_FORMAT, userIp, body); + } + private boolean lock(HttpServletRequest request) { - final String rmapKey = ((CustomHttpServletRequestWrapper) request).getBody(); + final String rmapKey = getRmapKey(request); RMap redissonClientMap = redissonClient.getMap(REDIS_KEY); return redissonClientMap.putIfAbsent(rmapKey, RMAP_VALUE) == null; } private void unLock(HttpServletRequest request) { - final String rmapKey = ((CustomHttpServletRequestWrapper) request).getBody(); + final String rmapKey = getRmapKey(request); RMap redissonClientMap = redissonClient.getMap(REDIS_KEY); redissonClientMap.remove(rmapKey); } From 24f89d122b1e8f170581aba85cecd2c058750a10 Mon Sep 17 00:00:00 2001 From: KWY Date: Mon, 13 May 2024 13:34:29 +0900 Subject: [PATCH 43/50] =?UTF-8?q?#259=20[feat]=20meeting=20dto=20record?= =?UTF-8?q?=EB=A1=9C=20=EC=9D=B4=EC=A0=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/request/MeetingSaveRequestDto.java | 78 ++++++++----------- .../dto/request/PreferTimeSaveRequestDto.java | 18 ++--- .../asap/server/service/MeetingService.java | 18 ++--- .../server/service/PreferTimeService.java | 8 +- 4 files changed, 51 insertions(+), 71 deletions(-) diff --git a/src/main/java/com/asap/server/controller/dto/request/MeetingSaveRequestDto.java b/src/main/java/com/asap/server/controller/dto/request/MeetingSaveRequestDto.java index 6d816f42..f9070d89 100644 --- a/src/main/java/com/asap/server/controller/dto/request/MeetingSaveRequestDto.java +++ b/src/main/java/com/asap/server/controller/dto/request/MeetingSaveRequestDto.java @@ -2,57 +2,43 @@ import com.asap.server.domain.enums.Duration; import com.asap.server.domain.enums.PlaceType; - -import java.util.List; +import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.Pattern; import jakarta.validation.constraints.Size; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.AccessLevel; -import lombok.Getter; -import lombok.NoArgsConstructor; +import java.util.List; -@Getter -@NoArgsConstructor(access = AccessLevel.PROTECTED) @Schema(description = "회의 생성 DTO") -public class MeetingSaveRequestDto { - - @NotBlank(message = "회의 제목이 입력되지 않았습니다.") - @Size(max = 15, message = "제목의 최대 입력 길이(15자)를 초과했습니다.") - @Schema(description = "회의 주제") - private String title; - - @Schema(description = "회의 가능 날짜", example = "[\"2023/07/09/MON\"]") - private List<@Pattern(regexp = "\\d\\d\\d\\d/\\d\\d/\\d\\d/[a-zA-Z][a-zA-Z][a-zA-Z]", message = "회의 가능 날짜 형식은 YYYY/mm/dd/ddd 입니다.") String> availableDates; - - @Schema(description = "회의 선호 시간") - private List preferTimes; - - @NotNull(message = "회의 형식이 입력되지 않았습니다.") - @Schema(description = "회의 방식", example = "ONLINE", allowableValues = {"ONLINE", "OFFLINE", "UNDEFINED"}) - private PlaceType place; - - @Schema(description = "회의 장소 설명") - private String placeDetail; - - @Schema(description = "회의 진행 시간", example = "HALF", allowableValues = {"HALF" , "HOUR", "HOUR_HALF", "TWO_HOUR", "TWO_HOUR_HALF", "THREE_HOUR"}) - @NotNull(message = "회의 진행 시간이 입력되지 않았습니다.") - private Duration duration; - - @Schema(description = "회의 방장 이름", example = "김아삽") - @NotBlank(message = "방장의 이름이 입력되지 않았습니다.") - @Size(max = 8, message = "방장 이름의 최대 입력 길이(8자)를 초과했습니다.") - private String name; - - @Schema(description = "회의 비밀번호", example = "0808") - @NotBlank(message = "회의 비밀번호가 입력되지 않았습니다.") - @Size(min = 4, message = "비밀번호의 최소 입력 길이는 4자입니다.") - @Pattern(regexp = "\\d{4,}", message = "비밀번호는 4자리 이상 숫자입니다.") - private String password; - - @Schema(description = "회의 추가 정보") - @Size(max = 50, message = "추가 내용의 최대 입력 길이(50자)를 초과했습니다.") - private String additionalInfo; +public record MeetingSaveRequestDto( + @NotBlank(message = "회의 제목이 입력되지 않았습니다.") + @Size(max = 15, message = "제목의 최대 입력 길이(15자)를 초과했습니다.") + @Schema(description = "회의 주제") + String title, + @Schema(description = "회의 가능 날짜", example = "[\"2024/07/09/MON\"]") + List<@Pattern(regexp = "\\d\\d\\d\\d/\\d\\d/\\d\\d/[a-zA-Z][a-zA-Z][a-zA-Z]", message = "회의 가능 날짜 형식은 YYYY/mm/dd/ddd 입니다.") String> availableDates, + @Schema(description = "회의 선호 시간") + List preferTimes, + @NotNull(message = "회의 형식이 입력되지 않았습니다.") + @Schema(description = "회의 방식", example = "ONLINE", allowableValues = {"ONLINE", "OFFLINE", "UNDEFINED"}) + PlaceType place, + @Schema(description = "회의 장소 설명") + String placeDetail, + @Schema(description = "회의 진행 시간", example = "HALF", allowableValues = {"HALF", "HOUR", "HOUR_HALF", "TWO_HOUR", "TWO_HOUR_HALF", "THREE_HOUR"}) + @NotNull(message = "회의 진행 시간이 입력되지 않았습니다.") + Duration duration, + @Schema(description = "회의 방장 이름", example = "김아삽") + @NotBlank(message = "방장의 이름이 입력되지 않았습니다.") + @Size(max = 8, message = "방장 이름의 최대 입력 길이(8자)를 초과했습니다.") + String name, + @Schema(description = "회의 비밀번호", example = "0808") + @NotBlank(message = "회의 비밀번호가 입력되지 않았습니다.") + @Size(min = 4, message = "비밀번호의 최소 입력 길이는 4자입니다.") + @Pattern(regexp = "\\d{4,}", message = "비밀번호는 4자리 이상 숫자입니다.") + String password, + @Schema(description = "회의 추가 정보") + @Size(max = 50, message = "추가 내용의 최대 입력 길이(50자)를 초과했습니다.") + String additionalInfo +) { } diff --git a/src/main/java/com/asap/server/controller/dto/request/PreferTimeSaveRequestDto.java b/src/main/java/com/asap/server/controller/dto/request/PreferTimeSaveRequestDto.java index 80cdff5c..e3596ed4 100644 --- a/src/main/java/com/asap/server/controller/dto/request/PreferTimeSaveRequestDto.java +++ b/src/main/java/com/asap/server/controller/dto/request/PreferTimeSaveRequestDto.java @@ -2,18 +2,12 @@ import com.asap.server.domain.enums.TimeSlot; import io.swagger.v3.oas.annotations.media.Schema; -import lombok.AccessLevel; -import lombok.Getter; -import lombok.NoArgsConstructor; +public record PreferTimeSaveRequestDto( + @Schema(description = "선호 시간(시작)", example = "09:00") + TimeSlot startTime, -@Getter -@NoArgsConstructor(access = AccessLevel.PROTECTED) -public class PreferTimeSaveRequestDto { - - @Schema(description = "선호 시간(시작)", example = "09:00") - private TimeSlot startTime; - - @Schema(description = "선호 시간(끝)", example = "11:00") - private TimeSlot endTime; + @Schema(description = "선호 시간(끝)", example = "11:00") + TimeSlot endTime +) { } diff --git a/src/main/java/com/asap/server/service/MeetingService.java b/src/main/java/com/asap/server/service/MeetingService.java index 7de1b099..910ea1c1 100644 --- a/src/main/java/com/asap/server/service/MeetingService.java +++ b/src/main/java/com/asap/server/service/MeetingService.java @@ -54,25 +54,25 @@ public class MeetingService { @Transactional public MeetingSaveResponseDto create(final MeetingSaveRequestDto meetingSaveRequestDto) { - String encryptedPassword = passwordEncoder.encode(meetingSaveRequestDto.getPassword()); + String encryptedPassword = passwordEncoder.encode(meetingSaveRequestDto.password()); Meeting meeting = Meeting.builder() - .title(meetingSaveRequestDto.getTitle()) + .title(meetingSaveRequestDto.title()) .password(encryptedPassword) - .additionalInfo(meetingSaveRequestDto.getAdditionalInfo()) - .duration(meetingSaveRequestDto.getDuration()) + .additionalInfo(meetingSaveRequestDto.additionalInfo()) + .duration(meetingSaveRequestDto.duration()) .place( Place.builder() - .placeType(meetingSaveRequestDto.getPlace()) - .placeDetail(meetingSaveRequestDto.getPlaceDetail()) + .placeType(meetingSaveRequestDto.place()) + .placeDetail(meetingSaveRequestDto.placeDetail()) .build()) .build(); meetingRepository.save(meeting); - User host = userService.createUser(meeting, meetingSaveRequestDto.getName(), Role.HOST); + User host = userService.createUser(meeting, meetingSaveRequestDto.name(), Role.HOST); - preferTimeService.create(meeting, meetingSaveRequestDto.getPreferTimes()); - availableDateService.create(meeting, meetingSaveRequestDto.getAvailableDates()); + preferTimeService.create(meeting, meetingSaveRequestDto.preferTimes()); + availableDateService.create(meeting, meetingSaveRequestDto.availableDates()); meeting.setHost(host); diff --git a/src/main/java/com/asap/server/service/PreferTimeService.java b/src/main/java/com/asap/server/service/PreferTimeService.java index 6153cdcd..8e40110e 100644 --- a/src/main/java/com/asap/server/service/PreferTimeService.java +++ b/src/main/java/com/asap/server/service/PreferTimeService.java @@ -27,12 +27,12 @@ public void create(final Meeting meeting, throw new BadRequestException(Error.DUPLICATED_TIME_EXCEPTION); } saveRequestDtos.stream() - .sorted(Comparator.comparing(preferTime -> preferTime.getStartTime().getTime())) + .sorted(Comparator.comparing(preferTime -> preferTime.startTime().getTime())) .map(preferTime -> preferTimeRepository.save( PreferTime.builder() .meeting(meeting) - .startTime(preferTime.getStartTime()) - .endTime(preferTime.getEndTime()).build())) + .startTime(preferTime.startTime()) + .endTime(preferTime.endTime()).build())) .collect(Collectors.toList()); } @@ -50,7 +50,7 @@ public List getPreferTimes(final Meeting meeting) { private boolean isPreferTimeDuplicated(List requestDtos) { List timeSlots = requestDtos.stream() - .flatMap(requestDto -> TimeSlot.getTimeSlots(requestDto.getStartTime().ordinal(), requestDto.getEndTime().ordinal() - 1).stream()) + .flatMap(requestDto -> TimeSlot.getTimeSlots(requestDto.startTime().ordinal(), requestDto.endTime().ordinal() - 1).stream()) .collect(Collectors.toList()); return timeSlots.size() != timeSlots.stream().distinct().count(); } From 00ebdefbe95539dfbd2ce6700090685a4c8125cd Mon Sep 17 00:00:00 2001 From: KWY Date: Mon, 13 May 2024 13:36:27 +0900 Subject: [PATCH 44/50] =?UTF-8?q?#259=20[test]=20=EC=A4=91=EB=B3=B5=20?= =?UTF-8?q?=EC=9A=94=EC=B2=AD=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=BD=94?= =?UTF-8?q?=EB=93=9C=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DuplicatedInterceptorTest.java | 96 +++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 src/test/java/com/asap/server/concurrency/DuplicatedInterceptorTest.java diff --git a/src/test/java/com/asap/server/concurrency/DuplicatedInterceptorTest.java b/src/test/java/com/asap/server/concurrency/DuplicatedInterceptorTest.java new file mode 100644 index 00000000..65522b4b --- /dev/null +++ b/src/test/java/com/asap/server/concurrency/DuplicatedInterceptorTest.java @@ -0,0 +1,96 @@ +package com.asap.server.concurrency; + +import com.asap.server.ServerApplication; +import com.asap.server.controller.dto.request.MeetingSaveRequestDto; +import com.asap.server.controller.dto.request.PreferTimeSaveRequestDto; +import com.asap.server.domain.enums.Duration; +import com.asap.server.domain.enums.PlaceType; +import com.asap.server.domain.enums.TimeSlot; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.MvcResult; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; + + +@SpringBootTest +@AutoConfigureMockMvc +public class DuplicatedInterceptorTest { + @Autowired + private MockMvc mockMvc; + @Autowired + private ObjectMapper objectMapper; + + @Test + @DisplayName("같은 사용자에게 회의 생성 요청이 연속해서 들어온다면 429 에러를 반환한다") + public void multipleRequestTest() throws Exception { + // given + int numberOfThread = 4; + ExecutorService executorService = Executors.newFixedThreadPool(numberOfThread); + CountDownLatch latch = new CountDownLatch(numberOfThread); + + MeetingSaveRequestDto bodyDto = new MeetingSaveRequestDto( + "title", + List.of("2024/07/09/MON", "2024/07/10/TUE"), + List.of(new PreferTimeSaveRequestDto(TimeSlot.SLOT_6_00, TimeSlot.SLOT_6_30)), + PlaceType.OFFLINE, + "회의 장소 설명", + Duration.HOUR, + "방장 이름", + "1234", + "회의 추가 정보" + ); + + String body = objectMapper.writeValueAsString(bodyDto); + + // when + List results = new ArrayList<>(); + for (int i = 0; i < numberOfThread; i++) { + executorService.submit(() -> { + try { + MvcResult result = mockMvc.perform( + post("/meeting") + .header("x-real-ip", "0.0.0.1") + .contentType(MediaType.APPLICATION_JSON) + .content(body) + ) + .andReturn(); + synchronized (results) { + results.add(result); + } + } catch (Exception e) { + throw new RuntimeException(e); + } finally { + latch.countDown(); + } + }); + } + latch.await(); + + // then + int count200 = 0; + int count429 = 0; + for (MvcResult mvcResult : results) { + if (mvcResult.getResponse().getStatus() == HttpStatus.OK.value()) count200++; + else if (mvcResult.getResponse().getStatus() == HttpStatus.TOO_MANY_REQUESTS.value()) count429++; + } + + assertThat(count200).isEqualTo(1); + assertThat(count429).isEqualTo(numberOfThread - 1); + } +} From 750420c252a89c0feaebfaaa5b2ebbbc23167df2 Mon Sep 17 00:00:00 2001 From: KWY Date: Mon, 13 May 2024 13:43:15 +0900 Subject: [PATCH 45/50] =?UTF-8?q?#259=20[feat]=20ci=20=EB=82=B4=20redis=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/dev-ci.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/.github/workflows/dev-ci.yml b/.github/workflows/dev-ci.yml index 958d1b6d..1b5cb119 100644 --- a/.github/workflows/dev-ci.yml +++ b/.github/workflows/dev-ci.yml @@ -17,6 +17,11 @@ permissions: jobs: build: runs-on: ubuntu-latest + strategy: + matrix: + node-version: [18.x, 20.x] + redis-version: [6, 7] + steps: - name: Setup MySQL uses: samin/mysql-action@v1 @@ -25,6 +30,11 @@ jobs: mysql user: 'asap' mysql password: 'asap' + - name: Set up redis + uses: supercharge/redis-github-action@1.7.0 + with: + node-version: ${{ matrix.node-version }} + - uses: actions/checkout@v3 - name: Set up JDK 17 uses: actions/setup-java@v3 From d92323db16fbe26ece82b13525bdfd31c0ff470d Mon Sep 17 00:00:00 2001 From: KWY Date: Mon, 13 May 2024 14:43:42 +0900 Subject: [PATCH 46/50] #259 [ci] edit ci mysql --- .github/workflows/dev-ci.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/dev-ci.yml b/.github/workflows/dev-ci.yml index 1b5cb119..875c88a4 100644 --- a/.github/workflows/dev-ci.yml +++ b/.github/workflows/dev-ci.yml @@ -24,11 +24,13 @@ jobs: steps: - name: Setup MySQL - uses: samin/mysql-action@v1 + uses: mirromutth/mysql-action@v1 with: mysql root password: 'asap' mysql user: 'asap' mysql password: 'asap' + host port: 3306 + container port: 3306 - name: Set up redis uses: supercharge/redis-github-action@1.7.0 From 5202300f5207ec61314b6a61918b0d5e965005c3 Mon Sep 17 00:00:00 2001 From: KWY Date: Mon, 13 May 2024 14:57:49 +0900 Subject: [PATCH 47/50] #259 [ci] edit type --- .github/workflows/dev-ci.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/dev-ci.yml b/.github/workflows/dev-ci.yml index 875c88a4..e68e9e54 100644 --- a/.github/workflows/dev-ci.yml +++ b/.github/workflows/dev-ci.yml @@ -21,14 +21,14 @@ jobs: matrix: node-version: [18.x, 20.x] redis-version: [6, 7] - + steps: - name: Setup MySQL uses: mirromutth/mysql-action@v1 with: - mysql root password: 'asap' - mysql user: 'asap' - mysql password: 'asap' + mysql root password: asap + mysql user: asap + mysql password: asap host port: 3306 container port: 3306 From 10ae8a060dd4123872f400e7cbac1f7bfa3c2d0c Mon Sep 17 00:00:00 2001 From: KWY Date: Mon, 13 May 2024 15:03:35 +0900 Subject: [PATCH 48/50] #259 [ci] edit type --- .github/workflows/dev-ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/dev-ci.yml b/.github/workflows/dev-ci.yml index e68e9e54..79b7d5f3 100644 --- a/.github/workflows/dev-ci.yml +++ b/.github/workflows/dev-ci.yml @@ -26,9 +26,9 @@ jobs: - name: Setup MySQL uses: mirromutth/mysql-action@v1 with: - mysql root password: asap - mysql user: asap - mysql password: asap + mysql root password: 'asap' + mysql user: 'asap' + mysql password: 'asap' host port: 3306 container port: 3306 From 3c212b3ffedb9cf94525967d9e2f729da5f691aa Mon Sep 17 00:00:00 2001 From: KWY Date: Mon, 13 May 2024 15:08:13 +0900 Subject: [PATCH 49/50] #259 [ci] change build --- .github/workflows/dev-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dev-ci.yml b/.github/workflows/dev-ci.yml index 79b7d5f3..6be87dc2 100644 --- a/.github/workflows/dev-ci.yml +++ b/.github/workflows/dev-ci.yml @@ -72,4 +72,4 @@ jobs: done - name: Build with Gradle # 실제 application build - run: ./gradlew clean build + run: ./gradlew clean --stacktrace --info build From 03d84e53134165926b7b69ebb200ceea3fb4691c Mon Sep 17 00:00:00 2001 From: KWY Date: Mon, 13 May 2024 15:27:29 +0900 Subject: [PATCH 50/50] =?UTF-8?q?#259=20[test]=20springboottest=20?= =?UTF-8?q?=EC=A3=BC=EC=84=9D=20=ED=95=B4=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/dev-ci.yml | 2 +- .../meeting/ConfirmMeetingMethodTest.java | 114 +++++++++--------- 2 files changed, 58 insertions(+), 58 deletions(-) diff --git a/.github/workflows/dev-ci.yml b/.github/workflows/dev-ci.yml index 6be87dc2..0bd78ee6 100644 --- a/.github/workflows/dev-ci.yml +++ b/.github/workflows/dev-ci.yml @@ -55,7 +55,7 @@ jobs: touch ./application.yml # GitHub-Actions 에서 설정한 값을 application.yml 파일에 쓰기 - echo "${{ secrets.DEV_APPLICATION_YAML }}" > ./application.yml + echo "${{ secrets.DEV_APPLICATION_YAML }}" >> ./application.yml # application.yml 파일 확인 cat ./application.yml diff --git a/src/test/java/com/asap/server/service/meeting/ConfirmMeetingMethodTest.java b/src/test/java/com/asap/server/service/meeting/ConfirmMeetingMethodTest.java index 75b39ba7..bb101d73 100644 --- a/src/test/java/com/asap/server/service/meeting/ConfirmMeetingMethodTest.java +++ b/src/test/java/com/asap/server/service/meeting/ConfirmMeetingMethodTest.java @@ -21,60 +21,60 @@ import static org.assertj.core.api.AssertionsForClassTypes.assertThat; -//@SpringBootTest -//@Transactional -//public class ConfirmMeetingMethodTest { -// @Autowired -// private MeetingService meetingService; -// @Autowired -// private EntityManager em; -// -// @Test -// @DisplayName("회의 확정시 ConfirmedDateTime 은 Update 된다.") -// void setConfirmDateTimeTest() { -// // given -// final Place place = Place.builder() -// .placeType(PlaceType.OFFLINE) -// .build(); -// final Meeting meeting = Meeting.builder() -// .title("회의 테스트") -// .password("0000") -// .additionalInfo("") -// .duration(Duration.HALF) -// .place(place) -// .build(); -// final User user = User.builder() -// .meeting(meeting) -// .name("강원용") -// .role(Role.HOST) -// .isFixed(false) -// .build(); -// meeting.setHost(user); -// -// em.persist(meeting); -// em.persist(user); -// em.flush(); -// em.clear(); -// -// final UserRequestDto userDto = UserRequestDto.builder() -// .id(user.getId()) -// .name(user.getName()) -// .build(); -// final MeetingConfirmRequestDto body = MeetingConfirmRequestDto.builder() -// .month("09") -// .day("07") -// .dayOfWeek("월") -// .startTime(TimeSlot.SLOT_6_00) -// .endTime(TimeSlot.SLOT_6_30) -// .users(List.of(userDto)) -// .build(); -// -// // when -// meetingService.confirmMeeting(body, meeting.getId(), user.getId()); -// -// // then -// final Meeting result = em.find(Meeting.class, meeting.getId()); -// assertThat(result.isConfirmedMeeting()).isTrue(); -// } -// -//} +@SpringBootTest +@Transactional +public class ConfirmMeetingMethodTest { + @Autowired + private MeetingService meetingService; + @Autowired + private EntityManager em; + + @Test + @DisplayName("회의 확정시 ConfirmedDateTime 은 Update 된다.") + void setConfirmDateTimeTest() { + // given + final Place place = Place.builder() + .placeType(PlaceType.OFFLINE) + .build(); + final Meeting meeting = Meeting.builder() + .title("회의 테스트") + .password("0000") + .additionalInfo("") + .duration(Duration.HALF) + .place(place) + .build(); + final User user = User.builder() + .meeting(meeting) + .name("강원용") + .role(Role.HOST) + .isFixed(false) + .build(); + meeting.setHost(user); + + em.persist(meeting); + em.persist(user); + em.flush(); + em.clear(); + + final UserRequestDto userDto = UserRequestDto.builder() + .id(user.getId()) + .name(user.getName()) + .build(); + final MeetingConfirmRequestDto body = MeetingConfirmRequestDto.builder() + .month("09") + .day("07") + .dayOfWeek("월") + .startTime(TimeSlot.SLOT_6_00) + .endTime(TimeSlot.SLOT_6_30) + .users(List.of(userDto)) + .build(); + + // when + meetingService.confirmMeeting(body, meeting.getId(), user.getId()); + + // then + final Meeting result = em.find(Meeting.class, meeting.getId()); + assertThat(result.isConfirmedMeeting()).isTrue(); + } + +}