From d1e282460b74730f9e3f2b8bf527ffb155d0ee8b Mon Sep 17 00:00:00 2001 From: kimyechan Date: Sun, 30 Jun 2024 18:50:02 +0900 Subject: [PATCH 01/19] =?UTF-8?q?Test:=20=EB=B8=94=EB=A3=A8-=EA=B7=B8?= =?UTF-8?q?=EB=A6=B0=20=EB=AC=B4=EC=A4=91=EB=8B=A8=20=EB=B0=B0=ED=8F=AC=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/deploy-prod.yaml | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/.github/workflows/deploy-prod.yaml b/.github/workflows/deploy-prod.yaml index 825c94f..23f27c9 100644 --- a/.github/workflows/deploy-prod.yaml +++ b/.github/workflows/deploy-prod.yaml @@ -2,7 +2,7 @@ name: deploy on prod server on: push: - branches: [main] + branches: [feat/blue-green] jobs: deploy: @@ -53,10 +53,9 @@ jobs: host: ${{ secrets.PROD_SERVER_HOST }} username: ${{ secrets.PROD_SERVER_USERNAME }} key: ${{ secrets.PROD_SERVER_PEM_KEY }} - envs: GITHUB_SHA + envs: + DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }} + DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }} script: | - sudo docker stop $(sudo docker ps -a -q) - sudo docker rm $(sudo docker ps -a -q) - sudo docker pull ${{secrets.DOCKERHUB_USERNAME}}/qtudy-server:prod - sudo docker run -d -p 8080:8080 --name qtudy-server-container ${{secrets.DOCKERHUB_USERNAME}}/qtudy-server:prod - sudo docker image prune -f + chmod +x /home/${{ secrets.PROD_SERVER_USERNAME }}/scripts/zero-downtime-deploy.sh + /home/${{ secrets.PROD_SERVER_USERNAME }}/scripts/zero-downtime-deploy.sh \ No newline at end of file From 58410aa170c115158edb007743dd81b1f94ce8d5 Mon Sep 17 00:00:00 2001 From: kimyechan Date: Sun, 30 Jun 2024 18:55:07 +0900 Subject: [PATCH 02/19] =?UTF-8?q?Test:=20=EB=B8=94=EB=A3=A8-=EA=B7=B8?= =?UTF-8?q?=EB=A6=B0=20=EB=AC=B4=EC=A4=91=EB=8B=A8=20=EB=B0=B0=ED=8F=AC=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/deploy-prod.yaml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/deploy-prod.yaml b/.github/workflows/deploy-prod.yaml index 23f27c9..c83cf95 100644 --- a/.github/workflows/deploy-prod.yaml +++ b/.github/workflows/deploy-prod.yaml @@ -53,9 +53,9 @@ jobs: host: ${{ secrets.PROD_SERVER_HOST }} username: ${{ secrets.PROD_SERVER_USERNAME }} key: ${{ secrets.PROD_SERVER_PEM_KEY }} - envs: - DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }} - DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }} - script: | - chmod +x /home/${{ secrets.PROD_SERVER_USERNAME }}/scripts/zero-downtime-deploy.sh - /home/${{ secrets.PROD_SERVER_USERNAME }}/scripts/zero-downtime-deploy.sh \ No newline at end of file + env: + DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }} + DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }} + script: | + chmod +x /home/${{ secrets.PROD_SERVER_USERNAME }}/scripts/zero-downtime-deploy.sh + /home/${{ secrets.PROD_SERVER_USERNAME }}/scripts/zero-downtime-deploy.sh \ No newline at end of file From a19df3c76b9af256af5651b446fee2a5b6ea2ab9 Mon Sep 17 00:00:00 2001 From: kimyechan Date: Sun, 30 Jun 2024 18:57:09 +0900 Subject: [PATCH 03/19] =?UTF-8?q?Test:=20=EB=B8=94=EB=A3=A8-=EA=B7=B8?= =?UTF-8?q?=EB=A6=B0=20=EB=AC=B4=EC=A4=91=EB=8B=A8=20=EB=B0=B0=ED=8F=AC=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Test: 블루-그린 무중단 배포 테스트 Test: 블루-그린 무중단 배포 테스트 Test: 블루-그린 무중단 배포 테스트 Test: 블루-그린 무중단 배포 테스트 Test: 블루-그린 무중단 배포 테스트 Test: 블루-그린 무중단 배포 테스트 Test: 블루-그린 무중단 배포 테스트 Test: 블루-그린 무중단 배포 테스트 Test: 블루-그린 무중단 배포 테스트 Test: 블루-그린 무중단 배포 테스트 Test: 블루-그린 무중단 배포 테스트 Test: 블루-그린 무중단 배포 테스트 Test: 블루-그린 무중단 배포 테스트 Test: 블루-그린 무중단 배포 테스트 Test: 블루-그린 무중단 배포 테스트 Test: 블루-그린 무중단 배포 테스트 Test: 블루-그린 무중단 배포 테스트 Test: 블루-그린 무중단 배포 테스트 Test: 블루-그린 무중단 배포 테스트 Test: 블루-그린 무중단 배포 테스트 Test: 블루-그린 무중단 배포 테스트 Test: 블루-그린 무중단 배포 테스트 --- .github/workflows/deploy-prod.yaml | 61 ++++++++++++++++++++++++++---- scripts/zero-downtime-deploy.sh | 29 ++++++++++++++ 2 files changed, 83 insertions(+), 7 deletions(-) create mode 100644 scripts/zero-downtime-deploy.sh diff --git a/.github/workflows/deploy-prod.yaml b/.github/workflows/deploy-prod.yaml index c83cf95..efb38b8 100644 --- a/.github/workflows/deploy-prod.yaml +++ b/.github/workflows/deploy-prod.yaml @@ -47,15 +47,62 @@ jobs: push: true tags: ${{ secrets.DOCKERHUB_USERNAME }}/qtudy-server:prod - - name: EC2 서버에 배포 + - name: EC2 서버에 배포# uses: appleboy/ssh-action@master with: host: ${{ secrets.PROD_SERVER_HOST }} username: ${{ secrets.PROD_SERVER_USERNAME }} key: ${{ secrets.PROD_SERVER_PEM_KEY }} - env: - DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }} - DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }} - script: | - chmod +x /home/${{ secrets.PROD_SERVER_USERNAME }}/scripts/zero-downtime-deploy.sh - /home/${{ secrets.PROD_SERVER_USERNAME }}/scripts/zero-downtime-deploy.sh \ No newline at end of file + envs: GITHUB_SHA, DOCKERHUB_USERNAME + script: | + # 현재 활성화된 Nginx 설정 파일 확인 + CURRENT_CONF=$(sudo readlink /etc/nginx/sites-enabled/current) + echo "Current Nginx configuration: $CURRENT_CONF" + if [[ "$CURRENT_CONF" == *"blue" ]]; then + NEW_CONF="/etc/nginx/sites-available/green" + OLD_CONTAINER="blue-container" + NEW_CONTAINER="green-container" + NEW_PORT=8081 + else + NEW_CONF="/etc/nginx/sites-available/blue" + OLD_CONTAINER="green-container" + NEW_CONTAINER="blue-container" + NEW_PORT=8080 + fi + + echo "New Nginx configuration: $NEW_CONF" + echo "Old container: $OLD_CONTAINER" + echo "New container: $NEW_CONTAINER" + echo "New port: $NEW_PORT" + + # 새 Docker 이미지 가져오기 + sudo docker pull ${{ secrets.DOCKERHUB_USERNAME }}/qtudy-server:prod + + # 새로운 컨테이너 실행 + sudo docker run -d -p $NEW_PORT:8080 --name $NEW_CONTAINER ${{ secrets.DOCKERHUB_USERNAME }}/qtudy-server:prod + + # 새로운 컨테이너가 준비될 때까지 대기 + echo "Waiting for the new container to be ready..." + sleep 10 + + # 헬스 체크를 통해 새 컨테이너가 정상적으로 실행 중인지 확인 + until [[ "$(curl -s -o /dev/null -w ''%{http_code}'' http://localhost:$NEW_PORT)" == "200" || "$(curl -s -o /dev/null -w ''%{http_code}'' http://localhost:$NEW_PORT)" == "404" ]]; do + echo "Waiting for the new container to respond with HTTP 200 or 404..." + sleep 2 + done + + echo "New container is ready. Switching Nginx configuration." + + # Nginx 설정 파일 교체 및 재시작 + sudo ln -sf $NEW_CONF /etc/nginx/sites-enabled/current + sudo systemctl reload nginx + + # 이전 컨테이너 중지 및 제거 + sudo docker stop $OLD_CONTAINER + sudo docker rm $OLD_CONTAINER + + # 실행 중인 Docker 컨테이너 확인 + sudo docker ps + + # 사용하지 않는 Docker 이미지 정리 + sudo docker image prune -f \ No newline at end of file diff --git a/scripts/zero-downtime-deploy.sh b/scripts/zero-downtime-deploy.sh new file mode 100644 index 0000000..3c942ca --- /dev/null +++ b/scripts/zero-downtime-deploy.sh @@ -0,0 +1,29 @@ +set -e + +# DockerHub 로그인 +echo $DOCKERHUB_TOKEN | sudo docker login -u $DOCKERHUB_USERNAME --password-stdin + +# 새로운 버전 배포 (qtudy-blue) +sudo docker pull $DOCKERHUB_USERNAME/qtudy-server:prod +sudo docker run -d -p 8002:8080 --name qtudy-server-blue $DOCKERHUB_USERNAME/qtudy-server:prod +sudo mv /etc/nginx/conf.d/qtudy-green.conf /etc/nginx/conf.d/qtudy-green.conf.backup +sudo mv /etc/nginx/conf.d/qtudy-blue.conf /etc/nginx/conf.d/qtudy-green.conf +sudo systemctl restart nginx + +# 새로운 버전 확인 +sleep 30 +if curl -f http://127.0.0.1; then + echo "새 버전이 정상적으로 실행되고 있습니다. 이전 컨테이너를 정리합니다." + sudo docker stop qtudy-server-container + sudo docker rm qtudy-server-container + sudo docker image prune -f +else + echo "새 버전 실행에 실패했습니다. 롤백을 진행합니다." + sudo mv /etc/nginx/conf.d/qtudy-green.conf /etc/nginx/conf.d/qtudy-blue.conf + sudo mv /etc/nginx/conf.d/qtudy-green.conf.backup /etc/nginx/conf.d/qtudy-green.conf + sudo systemctl restart nginx + sudo docker stop qtudy-server-blue + sudo docker rm qtudy-server-blue + sudo docker image prune -f + exit 1 +fi \ No newline at end of file From 53a5ab2496bc5e91f5b0e34fd4a9ab1b4327f446 Mon Sep 17 00:00:00 2001 From: kimyechan Date: Mon, 1 Jul 2024 12:42:26 +0900 Subject: [PATCH 04/19] =?UTF-8?q?Feat:=20Actuator=20=EC=9D=98=EC=A1=B4?= =?UTF-8?q?=EC=84=B1=20=EC=B6=94=EA=B0=80=20=EB=B0=8F=20=ED=97=AC=EC=8A=A4?= =?UTF-8?q?=EC=B2=B4=ED=81=AC=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/deploy-prod.yaml | 2 +- build.gradle | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/deploy-prod.yaml b/.github/workflows/deploy-prod.yaml index efb38b8..eab510f 100644 --- a/.github/workflows/deploy-prod.yaml +++ b/.github/workflows/deploy-prod.yaml @@ -86,7 +86,7 @@ jobs: sleep 10 # 헬스 체크를 통해 새 컨테이너가 정상적으로 실행 중인지 확인 - until [[ "$(curl -s -o /dev/null -w ''%{http_code}'' http://localhost:$NEW_PORT)" == "200" || "$(curl -s -o /dev/null -w ''%{http_code}'' http://localhost:$NEW_PORT)" == "404" ]]; do + until [[ "$(curl -s -o /dev/null -w ''%{http_code}'' http://localhost:$NEW_PORT/actuator/health)" == "200"]]; do echo "Waiting for the new container to respond with HTTP 200 or 404..." sleep 2 done diff --git a/build.gradle b/build.gradle index 90dbf9e..0a2a3d4 100644 --- a/build.gradle +++ b/build.gradle @@ -49,6 +49,9 @@ dependencies { implementation 'org.mapstruct:mapstruct:1.5.3.Final' annotationProcessor 'org.mapstruct:mapstruct-processor:1.5.3.Final' + // Spring Boot Actuator + implementation 'org.springframework.boot:spring-boot-starter-actuator' + // GPT 스크립트 테스트 편의성을 위해 추가 testAnnotationProcessor 'org.projectlombok:lombok' testImplementation 'com.theokanning.openai-gpt3-java:service:0.18.2' From 8702ce44ccfe060f267e7ce724136f191008e7b4 Mon Sep 17 00:00:00 2001 From: kimyechan Date: Mon, 1 Jul 2024 12:46:29 +0900 Subject: [PATCH 05/19] =?UTF-8?q?Fix:=20=EC=8A=A4=ED=81=AC=EB=A6=BD?= =?UTF-8?q?=ED=8A=B8=20=EC=98=A4=ED=83=80=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/deploy-prod.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/deploy-prod.yaml b/.github/workflows/deploy-prod.yaml index eab510f..6fcd3c0 100644 --- a/.github/workflows/deploy-prod.yaml +++ b/.github/workflows/deploy-prod.yaml @@ -86,8 +86,8 @@ jobs: sleep 10 # 헬스 체크를 통해 새 컨테이너가 정상적으로 실행 중인지 확인 - until [[ "$(curl -s -o /dev/null -w ''%{http_code}'' http://localhost:$NEW_PORT/actuator/health)" == "200"]]; do - echo "Waiting for the new container to respond with HTTP 200 or 404..." + until [[ "$(curl -s -o /dev/null -w ''%{http_code}'' http://localhost:$NEW_PORT/actuator/health)" == "200" ]]; do + echo "Waiting for the new container to respond with HTTP 200..." sleep 2 done From 098dd59930acfacb06471fbe9882ad6b2c6c6f99 Mon Sep 17 00:00:00 2001 From: kimyechan Date: Mon, 1 Jul 2024 12:51:01 +0900 Subject: [PATCH 06/19] =?UTF-8?q?Fix:=20=ED=8F=AC=ED=8A=B8=20=EC=B6=A9?= =?UTF-8?q?=EB=8F=8C=20=EC=BB=A8=ED=85=8C=EC=9D=B4=EB=84=88=20=ED=95=B4?= =?UTF-8?q?=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/deploy-prod.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy-prod.yaml b/.github/workflows/deploy-prod.yaml index 6fcd3c0..88da5f1 100644 --- a/.github/workflows/deploy-prod.yaml +++ b/.github/workflows/deploy-prod.yaml @@ -47,7 +47,7 @@ jobs: push: true tags: ${{ secrets.DOCKERHUB_USERNAME }}/qtudy-server:prod - - name: EC2 서버에 배포# + - name: EC2 서버에 배포 uses: appleboy/ssh-action@master with: host: ${{ secrets.PROD_SERVER_HOST }} From a93cca7f8c77cfc49cb9f5f3334be1a93eebd6de Mon Sep 17 00:00:00 2001 From: kimyechan Date: Mon, 1 Jul 2024 13:33:14 +0900 Subject: [PATCH 07/19] =?UTF-8?q?Fix:=20=EB=B8=8C=EB=9E=9C=EC=B9=98=20main?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/deploy-prod.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy-prod.yaml b/.github/workflows/deploy-prod.yaml index 88da5f1..5227943 100644 --- a/.github/workflows/deploy-prod.yaml +++ b/.github/workflows/deploy-prod.yaml @@ -2,7 +2,7 @@ name: deploy on prod server on: push: - branches: [feat/blue-green] + branches: [main] jobs: deploy: From e2f59498ef1cffc4513c7331fd191186bdd20328 Mon Sep 17 00:00:00 2001 From: kimyechan Date: Mon, 1 Jul 2024 13:51:23 +0900 Subject: [PATCH 08/19] =?UTF-8?q?Remove:=20=EC=8A=A4=ED=81=AC=EB=A6=BD?= =?UTF-8?q?=ED=8A=B8=20=EC=89=98=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/zero-downtime-deploy.sh | 29 ----------------------------- 1 file changed, 29 deletions(-) delete mode 100644 scripts/zero-downtime-deploy.sh diff --git a/scripts/zero-downtime-deploy.sh b/scripts/zero-downtime-deploy.sh deleted file mode 100644 index 3c942ca..0000000 --- a/scripts/zero-downtime-deploy.sh +++ /dev/null @@ -1,29 +0,0 @@ -set -e - -# DockerHub 로그인 -echo $DOCKERHUB_TOKEN | sudo docker login -u $DOCKERHUB_USERNAME --password-stdin - -# 새로운 버전 배포 (qtudy-blue) -sudo docker pull $DOCKERHUB_USERNAME/qtudy-server:prod -sudo docker run -d -p 8002:8080 --name qtudy-server-blue $DOCKERHUB_USERNAME/qtudy-server:prod -sudo mv /etc/nginx/conf.d/qtudy-green.conf /etc/nginx/conf.d/qtudy-green.conf.backup -sudo mv /etc/nginx/conf.d/qtudy-blue.conf /etc/nginx/conf.d/qtudy-green.conf -sudo systemctl restart nginx - -# 새로운 버전 확인 -sleep 30 -if curl -f http://127.0.0.1; then - echo "새 버전이 정상적으로 실행되고 있습니다. 이전 컨테이너를 정리합니다." - sudo docker stop qtudy-server-container - sudo docker rm qtudy-server-container - sudo docker image prune -f -else - echo "새 버전 실행에 실패했습니다. 롤백을 진행합니다." - sudo mv /etc/nginx/conf.d/qtudy-green.conf /etc/nginx/conf.d/qtudy-blue.conf - sudo mv /etc/nginx/conf.d/qtudy-green.conf.backup /etc/nginx/conf.d/qtudy-green.conf - sudo systemctl restart nginx - sudo docker stop qtudy-server-blue - sudo docker rm qtudy-server-blue - sudo docker image prune -f - exit 1 -fi \ No newline at end of file From 9bdc485e167af8321467378768fe1b8df704dcc6 Mon Sep 17 00:00:00 2001 From: kimyechan Date: Tue, 2 Jul 2024 11:44:03 +0900 Subject: [PATCH 09/19] =?UTF-8?q?Chore:=20Docker=20ps=20=EA=B5=AC=EB=AC=B8?= =?UTF-8?q?=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/deploy-prod.yaml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/workflows/deploy-prod.yaml b/.github/workflows/deploy-prod.yaml index 5227943..db5872e 100644 --- a/.github/workflows/deploy-prod.yaml +++ b/.github/workflows/deploy-prod.yaml @@ -101,8 +101,5 @@ jobs: sudo docker stop $OLD_CONTAINER sudo docker rm $OLD_CONTAINER - # 실행 중인 Docker 컨테이너 확인 - sudo docker ps - # 사용하지 않는 Docker 이미지 정리 sudo docker image prune -f \ No newline at end of file From 3118ff74a47e061a71cf8ce37336679c7d58aaf4 Mon Sep 17 00:00:00 2001 From: yujamint Date: Thu, 25 Jul 2024 09:24:45 +0900 Subject: [PATCH 10/19] =?UTF-8?q?fix:=20=EC=BA=90=EC=8B=9C=20=EC=88=98?= =?UTF-8?q?=EC=A0=95(draft)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/CategorizedProblemService.java | 12 ++++-- .../com/app/fake/FakeLoginController.java | 39 +++++++++++++++++++ .../java/com/app/fake/FakeSignUpRequest.java | 17 ++++++++ 3 files changed, 65 insertions(+), 3 deletions(-) create mode 100644 src/main/java/com/app/fake/FakeLoginController.java create mode 100644 src/main/java/com/app/fake/FakeSignUpRequest.java diff --git a/src/main/java/com/app/domain/categorizedproblem/service/CategorizedProblemService.java b/src/main/java/com/app/domain/categorizedproblem/service/CategorizedProblemService.java index a205b51..aff47ab 100644 --- a/src/main/java/com/app/domain/categorizedproblem/service/CategorizedProblemService.java +++ b/src/main/java/com/app/domain/categorizedproblem/service/CategorizedProblemService.java @@ -230,7 +230,7 @@ public MemberSavedSummaryDto.pdfResponse createCategorizedProblemsPdf(Long categ } - @CacheEvict(value = "categorizedProblem", key = "#categoryId") + @CacheEvict(value = "categorizedProblem", key = "#result.getCategory().getCategoryId()") public CategorizedProblem updateCategorizedProblem(Long categorizedProblemId, MemberSavedProblemDto.Patch problemPatchDto) { CategorizedProblem categorizedProblem = findVerifiedCategorizedProblemByCategorizedProblemId(categorizedProblemId); problemService.updateProblem( @@ -247,10 +247,16 @@ public Page findCategorizedProblemsByCategoryId(Long categor return categorizedProblemRepository.findByCategoryCategoryId(categoryId, pageRequest); } - @CacheEvict(value = "categorizedProblem", key = "#categoryId") + public void deleteCategorizedProblem(Long categorizedProblemID){ CategorizedProblem categorizedProblem = findVerifiedCategorizedProblemByCategorizedProblemId(categorizedProblemID); - categorizedProblemRepository.deleteById(categorizedProblemID); + Long categoryId = categorizedProblem.getCategory().getCategoryId(); + deleteAndEvictCache(categorizedProblem, categoryId); + } + + @CacheEvict(value = "categorizedProblem", key = "#categoryId") + public void deleteAndEvictCache(CategorizedProblem categorizedProblem, Long categoryId) { + categorizedProblemRepository.deleteById(categorizedProblem.getCategorizedProblemId()); Problem problem = categorizedProblem.getProblem(); Long problemId = problem.getProblemId(); diff --git a/src/main/java/com/app/fake/FakeLoginController.java b/src/main/java/com/app/fake/FakeLoginController.java new file mode 100644 index 0000000..ef57c48 --- /dev/null +++ b/src/main/java/com/app/fake/FakeLoginController.java @@ -0,0 +1,39 @@ +package com.app.fake; + +import com.app.domain.member.constant.MemberType; +import com.app.domain.member.constant.Role; +import com.app.domain.member.entity.Member; +import com.app.domain.member.service.MemberService; +import com.app.global.jwt.dto.JwtTokenDto; +import com.app.global.jwt.service.TokenManager; +import lombok.RequiredArgsConstructor; +import org.springframework.context.annotation.Profile; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; + +@RequiredArgsConstructor +@Profile(value = {"local", "test"}) +@RestController +public class FakeLoginController { + + private final MemberService memberService; + private final TokenManager tokenManager; + + @PostMapping("/api/fake/login") + public ResponseEntity fakeSignUp(@RequestBody FakeSignUpRequest request) { + Member member = memberService.findMemberByEmail(request.getEmail()).orElseGet( + () -> memberService.registerMember(Member.builder() + .nickName(request.getNickname()) + .email(request.getEmail()) + .memberType(MemberType.KAKAO) + .role(Role.USER) + .build()) + ); + + JwtTokenDto jwtTokenDto = tokenManager.createJwtTokenDto(member.getMemberId(), member.getRole()); + member.updateRefreshToken(jwtTokenDto); + return ResponseEntity.ok(jwtTokenDto.getAccessToken()); + } +} diff --git a/src/main/java/com/app/fake/FakeSignUpRequest.java b/src/main/java/com/app/fake/FakeSignUpRequest.java new file mode 100644 index 0000000..087d383 --- /dev/null +++ b/src/main/java/com/app/fake/FakeSignUpRequest.java @@ -0,0 +1,17 @@ +package com.app.fake; + +import lombok.Builder; +import lombok.Getter; + +@Getter +@Builder +public class FakeSignUpRequest { + + private String nickname; + private String email; + + public FakeSignUpRequest(String nickname, String email) { + this.nickname = nickname; + this.email = email; + } +} From 9ee74a01d792a55300fdf2c35bb13b4ffd671352 Mon Sep 17 00:00:00 2001 From: yujamint Date: Thu, 25 Jul 2024 23:04:20 +0900 Subject: [PATCH 11/19] =?UTF-8?q?fix:=20=EC=BA=90=EC=8B=9C=20=EC=B4=88?= =?UTF-8?q?=EA=B8=B0=ED=99=94=20=EB=AC=B8=EC=A0=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/CategorizedProblemService.java | 11 +++-------- .../service/CategorizedSummaryService.java | 8 +++++--- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/src/main/java/com/app/domain/categorizedproblem/service/CategorizedProblemService.java b/src/main/java/com/app/domain/categorizedproblem/service/CategorizedProblemService.java index aff47ab..9308e16 100644 --- a/src/main/java/com/app/domain/categorizedproblem/service/CategorizedProblemService.java +++ b/src/main/java/com/app/domain/categorizedproblem/service/CategorizedProblemService.java @@ -247,15 +247,9 @@ public Page findCategorizedProblemsByCategoryId(Long categor return categorizedProblemRepository.findByCategoryCategoryId(categoryId, pageRequest); } - - public void deleteCategorizedProblem(Long categorizedProblemID){ + @CacheEvict(value = "categorizedProblem", key = "#result") + public Long deleteCategorizedProblem(Long categorizedProblemID) { CategorizedProblem categorizedProblem = findVerifiedCategorizedProblemByCategorizedProblemId(categorizedProblemID); - Long categoryId = categorizedProblem.getCategory().getCategoryId(); - deleteAndEvictCache(categorizedProblem, categoryId); - } - - @CacheEvict(value = "categorizedProblem", key = "#categoryId") - public void deleteAndEvictCache(CategorizedProblem categorizedProblem, Long categoryId) { categorizedProblemRepository.deleteById(categorizedProblem.getCategorizedProblemId()); Problem problem = categorizedProblem.getProblem(); @@ -263,6 +257,7 @@ public void deleteAndEvictCache(CategorizedProblem categorizedProblem, Long cate if (problem.isMemberSavedProblem() && !isProblemUsedInOtherCategorizedProblems(problemId)) { problemService.deleteProblem(problemId); } + return categorizedProblem.getCategory().getCategoryId(); } private boolean isProblemUsedInOtherCategorizedProblems(Long problemId) { diff --git a/src/main/java/com/app/domain/categorizedsummary/service/CategorizedSummaryService.java b/src/main/java/com/app/domain/categorizedsummary/service/CategorizedSummaryService.java index 54e068c..c3678bc 100644 --- a/src/main/java/com/app/domain/categorizedsummary/service/CategorizedSummaryService.java +++ b/src/main/java/com/app/domain/categorizedsummary/service/CategorizedSummaryService.java @@ -76,7 +76,7 @@ public SummaryDto.pdfResponse createSummaryPdf(Long categorizedSummaryId) throws return summaryService.createSummaryPdf(summaryId); } - @CacheEvict(value = "categorizedSummary", key = "#categoryId") + @CacheEvict(value = "categorizedSummary", key = "#result.getCategory().getCategoryId()") public CategorizedSummary updateCategorizedSummary(Long categorizedSummaryId, SummaryDto.Patch summaryPatchDto) { CategorizedSummary categorizedSummary = findVerifiedCategorizedSummaryByCategorizedSummaryId(categorizedSummaryId); summaryService.updateSummary( @@ -87,8 +87,8 @@ public CategorizedSummary updateCategorizedSummary(Long categorizedSummaryId, Su return categorizedSummaryRepository.save(categorizedSummary); } - @CacheEvict(value = "categorizedSummary", key = "#categoryId") - public void deleteCategorizedSummary(Long categorizedSummaryId) { + @CacheEvict(value = "categorizedSummary", key = "#result") + public Long deleteCategorizedSummary(Long categorizedSummaryId) { CategorizedSummary categorizedSummary = findVerifiedCategorizedSummaryByCategorizedSummaryId(categorizedSummaryId); categorizedSummaryRepository.deleteById(categorizedSummaryId); @@ -98,6 +98,8 @@ public void deleteCategorizedSummary(Long categorizedSummaryId) { if (summary.isMemberSavedSummary() && !isSummaryUsedInOtherCategorizedSummarys(summaryId)) { summaryRepository.deleteById(summaryId); } + Long categoryId = categorizedSummary.getCategory().getCategoryId(); + return categoryId; } private boolean isSummaryUsedInOtherCategorizedSummarys(Long summaryId){ From 96ac64162e06ced85bc930d97083663509504875 Mon Sep 17 00:00:00 2001 From: yujamint Date: Thu, 25 Jul 2024 23:11:59 +0900 Subject: [PATCH 12/19] =?UTF-8?q?fix:=20FakeLoginController=20=EB=B9=88=20?= =?UTF-8?q?=EC=A4=91=EB=B3=B5=20=EC=83=9D=EC=84=B1=20=EB=AC=B8=EC=A0=9C=20?= =?UTF-8?q?=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../category/CategoryIntegrationTest.java | 2 +- .../integration/dto/FakeSignUpRequest.java | 17 -------- .../fake/FakeSignUpController.java | 40 ------------------- .../integration/file/FileIntegrationTest.java | 2 +- .../AiGeneratedProblemIntegrationTest.java | 2 +- .../CategorizedProblemIntegrationTest.java | 2 +- .../MemberSavedProblemIntegrationTest.java | 2 +- .../ProblemFileIntegrationTest.java | 2 +- .../AiGeneratedSummaryIntegrationTest.java | 2 +- .../CategorizedSummaryIntegrationTest.java | 2 +- .../MemberSavedSummaryIntegrationTest.java | 2 +- .../SummaryFileIntegrationTest.java | 2 +- 12 files changed, 10 insertions(+), 67 deletions(-) delete mode 100644 src/test/java/com/app/integration/dto/FakeSignUpRequest.java delete mode 100644 src/test/java/com/app/integration/fake/FakeSignUpController.java diff --git a/src/test/java/com/app/integration/category/CategoryIntegrationTest.java b/src/test/java/com/app/integration/category/CategoryIntegrationTest.java index 02ef5f7..45d8b7a 100644 --- a/src/test/java/com/app/integration/category/CategoryIntegrationTest.java +++ b/src/test/java/com/app/integration/category/CategoryIntegrationTest.java @@ -5,7 +5,7 @@ import com.app.domain.category.dto.CategoryDto; import com.app.domain.category.dto.CategoryDto.RequestDto; import com.app.domain.category.contsant.CategoryType; -import com.app.integration.dto.FakeSignUpRequest; +import com.app.fake.FakeSignUpRequest; import io.restassured.RestAssured; import io.restassured.response.ExtractableResponse; import io.restassured.response.Response; diff --git a/src/test/java/com/app/integration/dto/FakeSignUpRequest.java b/src/test/java/com/app/integration/dto/FakeSignUpRequest.java deleted file mode 100644 index 26fc84e..0000000 --- a/src/test/java/com/app/integration/dto/FakeSignUpRequest.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.app.integration.dto; - -import lombok.Builder; -import lombok.Getter; - -@Getter -@Builder -public class FakeSignUpRequest { - - private String nickname; - private String email; - - public FakeSignUpRequest(String nickname, String email) { - this.nickname = nickname; - this.email = email; - } -} diff --git a/src/test/java/com/app/integration/fake/FakeSignUpController.java b/src/test/java/com/app/integration/fake/FakeSignUpController.java deleted file mode 100644 index 6e5003c..0000000 --- a/src/test/java/com/app/integration/fake/FakeSignUpController.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.app.integration.fake; - -import com.app.domain.member.constant.MemberType; -import com.app.domain.member.constant.Role; -import com.app.domain.member.entity.Member; -import com.app.domain.member.service.MemberService; -import com.app.global.jwt.dto.JwtTokenDto; -import com.app.global.jwt.service.TokenManager; -import com.app.integration.dto.FakeSignUpRequest; -import lombok.RequiredArgsConstructor; -import org.springframework.context.annotation.Profile; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RestController; - -@RequiredArgsConstructor -@Profile(value = {"local", "test"}) -@RestController -public class FakeSignUpController { - - private final MemberService memberService; - private final TokenManager tokenManager; - - @PostMapping("/api/fake/login") - public ResponseEntity fakeSignUp(@RequestBody FakeSignUpRequest request) { - Member member = memberService.findMemberByEmail(request.getEmail()).orElseGet( - () -> memberService.registerMember(Member.builder() - .nickName(request.getNickname()) - .email(request.getEmail()) - .memberType(MemberType.KAKAO) - .role(Role.USER) - .build()) - ); - - JwtTokenDto jwtTokenDto = tokenManager.createJwtTokenDto(member.getMemberId(), member.getRole()); - member.updateRefreshToken(jwtTokenDto); - return ResponseEntity.ok(jwtTokenDto.getAccessToken()); - } -} diff --git a/src/test/java/com/app/integration/file/FileIntegrationTest.java b/src/test/java/com/app/integration/file/FileIntegrationTest.java index e388ad6..780e6dd 100644 --- a/src/test/java/com/app/integration/file/FileIntegrationTest.java +++ b/src/test/java/com/app/integration/file/FileIntegrationTest.java @@ -11,8 +11,8 @@ import com.app.domain.problem.aigeneratedproblem.repository.ProblemFileRepository; import com.app.domain.summary.aigeneratedsummary.entity.SummaryFile; import com.app.domain.summary.aigeneratedsummary.repository.SummaryFileRepository; +import com.app.fake.FakeSignUpRequest; import com.app.global.config.ENUM.PdfType; -import com.app.integration.dto.FakeSignUpRequest; import io.restassured.RestAssured; import io.restassured.response.ExtractableResponse; import io.restassured.response.Response; diff --git a/src/test/java/com/app/integration/problem/aigeneratedproblem/AiGeneratedProblemIntegrationTest.java b/src/test/java/com/app/integration/problem/aigeneratedproblem/AiGeneratedProblemIntegrationTest.java index 3ce5711..82b23e7 100644 --- a/src/test/java/com/app/integration/problem/aigeneratedproblem/AiGeneratedProblemIntegrationTest.java +++ b/src/test/java/com/app/integration/problem/aigeneratedproblem/AiGeneratedProblemIntegrationTest.java @@ -5,8 +5,8 @@ import com.app.domain.problem.aigeneratedproblem.repository.AiGeneratedProblemRepository; import com.app.domain.problem.aigeneratedproblem.repository.ProblemFileRepository; import com.app.domain.problem.aigeneratedproblem.service.AiGeneratedProblemService; +import com.app.fake.FakeSignUpRequest; import com.app.global.config.ENUM.ProblemType; -import com.app.integration.dto.FakeSignUpRequest; import io.restassured.RestAssured; import io.restassured.response.ExtractableResponse; import io.restassured.response.Response; diff --git a/src/test/java/com/app/integration/problem/categorizedproblem/CategorizedProblemIntegrationTest.java b/src/test/java/com/app/integration/problem/categorizedproblem/CategorizedProblemIntegrationTest.java index 9a156a5..69396de 100644 --- a/src/test/java/com/app/integration/problem/categorizedproblem/CategorizedProblemIntegrationTest.java +++ b/src/test/java/com/app/integration/problem/categorizedproblem/CategorizedProblemIntegrationTest.java @@ -4,8 +4,8 @@ import com.app.domain.category.contsant.CategoryType; import com.app.domain.category.dto.CategoryDto.RequestDto; +import com.app.fake.FakeSignUpRequest; import com.app.global.config.ENUM.ProblemType; -import com.app.integration.dto.FakeSignUpRequest; import com.app.domain.categorizedproblem.dto.CategorizedProblemDto; import com.app.domain.problem.membersavedproblem.dto.MemberSavedProblemDto; import io.restassured.RestAssured; diff --git a/src/test/java/com/app/integration/problem/membersavedproblem/MemberSavedProblemIntegrationTest.java b/src/test/java/com/app/integration/problem/membersavedproblem/MemberSavedProblemIntegrationTest.java index 3b5011b..1d60ac8 100644 --- a/src/test/java/com/app/integration/problem/membersavedproblem/MemberSavedProblemIntegrationTest.java +++ b/src/test/java/com/app/integration/problem/membersavedproblem/MemberSavedProblemIntegrationTest.java @@ -2,8 +2,8 @@ import static org.assertj.core.api.Assertions.assertThat; +import com.app.fake.FakeSignUpRequest; import com.app.global.config.ENUM.ProblemType; -import com.app.integration.dto.FakeSignUpRequest; import com.app.domain.problem.membersavedproblem.dto.MemberSavedProblemDto; import io.restassured.RestAssured; import io.restassured.response.ExtractableResponse; diff --git a/src/test/java/com/app/integration/problemfile/ProblemFileIntegrationTest.java b/src/test/java/com/app/integration/problemfile/ProblemFileIntegrationTest.java index aa32936..b53e3b2 100644 --- a/src/test/java/com/app/integration/problemfile/ProblemFileIntegrationTest.java +++ b/src/test/java/com/app/integration/problemfile/ProblemFileIntegrationTest.java @@ -1,11 +1,11 @@ package com.app.integration.problemfile; import com.app.domain.problem.aigeneratedproblem.dto.ProblemFile.Request.AiGenerateProblemDto; +import com.app.fake.FakeSignUpRequest; import com.app.global.config.ENUM.Amount; import com.app.global.config.ENUM.ProblemDifficulty; import com.app.global.config.ENUM.ProblemType; import com.app.global.config.S3.S3Service; -import com.app.integration.dto.FakeSignUpRequest; import io.restassured.RestAssured; import io.restassured.response.ExtractableResponse; import io.restassured.response.Response; diff --git a/src/test/java/com/app/integration/summary/aigeneratedsummary/AiGeneratedSummaryIntegrationTest.java b/src/test/java/com/app/integration/summary/aigeneratedsummary/AiGeneratedSummaryIntegrationTest.java index 20526a5..b3cb84c 100644 --- a/src/test/java/com/app/integration/summary/aigeneratedsummary/AiGeneratedSummaryIntegrationTest.java +++ b/src/test/java/com/app/integration/summary/aigeneratedsummary/AiGeneratedSummaryIntegrationTest.java @@ -3,7 +3,7 @@ import com.app.domain.summary.aigeneratedsummary.entity.AiGeneratedSummary; import com.app.domain.summary.aigeneratedsummary.entity.SummaryFile; import com.app.domain.summary.aigeneratedsummary.service.AiGeneratedSummaryService; -import com.app.integration.dto.FakeSignUpRequest; +import com.app.fake.FakeSignUpRequest; import io.restassured.RestAssured; import io.restassured.response.ExtractableResponse; import io.restassured.response.Response; diff --git a/src/test/java/com/app/integration/summary/categorizedsummary/CategorizedSummaryIntegrationTest.java b/src/test/java/com/app/integration/summary/categorizedsummary/CategorizedSummaryIntegrationTest.java index 194caea..a28d37e 100644 --- a/src/test/java/com/app/integration/summary/categorizedsummary/CategorizedSummaryIntegrationTest.java +++ b/src/test/java/com/app/integration/summary/categorizedsummary/CategorizedSummaryIntegrationTest.java @@ -5,8 +5,8 @@ import com.app.domain.category.contsant.CategoryType; import com.app.domain.category.dto.CategoryDto.RequestDto; import com.app.domain.summary.membersavedsummary.dto.MemberSavedSummaryDto; +import com.app.fake.FakeSignUpRequest; import com.app.global.config.ENUM.ProblemType; -import com.app.integration.dto.FakeSignUpRequest; import com.app.domain.categorizedsummary.dto.CategorizedSummaryDto; import com.app.domain.summary.dto.SummaryDto; import io.restassured.RestAssured; diff --git a/src/test/java/com/app/integration/summary/membersavedsummary/MemberSavedSummaryIntegrationTest.java b/src/test/java/com/app/integration/summary/membersavedsummary/MemberSavedSummaryIntegrationTest.java index 6d367d8..42c2a58 100644 --- a/src/test/java/com/app/integration/summary/membersavedsummary/MemberSavedSummaryIntegrationTest.java +++ b/src/test/java/com/app/integration/summary/membersavedsummary/MemberSavedSummaryIntegrationTest.java @@ -2,8 +2,8 @@ import static org.assertj.core.api.Assertions.assertThat; -import com.app.integration.dto.FakeSignUpRequest; import com.app.domain.summary.membersavedsummary.dto.MemberSavedSummaryDto; +import com.app.fake.FakeSignUpRequest; import io.restassured.RestAssured; import io.restassured.response.ExtractableResponse; import io.restassured.response.Response; diff --git a/src/test/java/com/app/integration/summaryfile/aigeneratedsummary/SummaryFileIntegrationTest.java b/src/test/java/com/app/integration/summaryfile/aigeneratedsummary/SummaryFileIntegrationTest.java index 4397bbb..f95f189 100644 --- a/src/test/java/com/app/integration/summaryfile/aigeneratedsummary/SummaryFileIntegrationTest.java +++ b/src/test/java/com/app/integration/summaryfile/aigeneratedsummary/SummaryFileIntegrationTest.java @@ -3,9 +3,9 @@ import com.app.domain.file.dto.Response.FileListResponseDto; import com.app.domain.summary.aigeneratedsummary.dto.SummaryFile.Request.AiGenerateSummaryDto; import com.app.domain.summary.aigeneratedsummary.dto.SummaryFile.Response.AiGenerateSummaryResponseDto; +import com.app.fake.FakeSignUpRequest; import com.app.global.config.ENUM.Amount; import com.app.global.config.S3.S3Service; -import com.app.integration.dto.FakeSignUpRequest; import com.jayway.jsonpath.TypeRef; import io.restassured.RestAssured; import io.restassured.response.ExtractableResponse; From b2b1b01431c4f987a196936578c64f4b14b1912e Mon Sep 17 00:00:00 2001 From: kimyechan Date: Sat, 13 Jul 2024 04:02:08 +0900 Subject: [PATCH 13/19] =?UTF-8?q?fix=20:=20AI=20PDF=20=ED=8C=8C=EC=9D=BC?= =?UTF-8?q?=20=EC=98=A4=EB=A5=98=20=EB=A1=9C=EA=B7=B8=20=EC=B6=9C=EB=A0=A5?= =?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 --- .../problem/aigeneratedproblem/service/ProblemFileService.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/com/app/domain/problem/aigeneratedproblem/service/ProblemFileService.java b/src/main/java/com/app/domain/problem/aigeneratedproblem/service/ProblemFileService.java index 26c0b6e..4f6e014 100644 --- a/src/main/java/com/app/domain/problem/aigeneratedproblem/service/ProblemFileService.java +++ b/src/main/java/com/app/domain/problem/aigeneratedproblem/service/ProblemFileService.java @@ -268,8 +268,7 @@ public void UploadS3(AiGenerateProblemFromAiDto[] aiGenerateProblemFromAiDto, Ai } catch (IOException e) { - - throw new BusinessException(ErrorCode.NOT_UPLOAD_PROBLEM); + e.printStackTrace(); } finally { if (tempFile != null) { tempFile.delete(); // 방금 생성한 파일 삭제 From 60ef81b2d20232a28bd309cfd5e61e33e5213cce Mon Sep 17 00:00:00 2001 From: kimyechan Date: Sat, 13 Jul 2024 04:03:49 +0900 Subject: [PATCH 14/19] =?UTF-8?q?fix=20:=20AI=20=EC=9A=94=EC=95=BD=20PDF?= =?UTF-8?q?=20=ED=8C=8C=EC=9D=BC=20=EC=98=A4=EB=A5=98=20=EB=A1=9C=EA=B7=B8?= =?UTF-8?q?=20=EC=B6=9C=EB=A0=A5=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../summary/aigeneratedsummary/service/SummaryFileService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/app/domain/summary/aigeneratedsummary/service/SummaryFileService.java b/src/main/java/com/app/domain/summary/aigeneratedsummary/service/SummaryFileService.java index 8039db7..04f5edb 100644 --- a/src/main/java/com/app/domain/summary/aigeneratedsummary/service/SummaryFileService.java +++ b/src/main/java/com/app/domain/summary/aigeneratedsummary/service/SummaryFileService.java @@ -207,7 +207,7 @@ public void UploadS3(AiGenerateSummaryFromAiDto aiGenerateSummaryFromAiDto, AiGe } catch (IOException e) { - throw new BusinessException(ErrorCode.NOT_UPLOAD_PROBLEM); + e.printStackTrace(); } finally { if (tempFile != null) { tempFile.delete(); // 방금 생성한 파일 삭제 From cc30329a0f728794e67d4ea7e9812c280db4ddc1 Mon Sep 17 00:00:00 2001 From: kimyechan Date: Sat, 13 Jul 2024 04:09:25 +0900 Subject: [PATCH 15/19] =?UTF-8?q?refactor=20:=20=EC=B9=B4=ED=85=8C?= =?UTF-8?q?=EA=B3=A0=EB=A6=AC=20=EA=B8=B0=EB=B0=98=20=EB=AC=B8=EC=A0=9C=20?= =?UTF-8?q?PDF=20=EC=83=9D=EC=84=B1=20=EB=A1=9C=EC=A7=81=20=EB=A6=AC?= =?UTF-8?q?=ED=8C=A9=ED=86=A0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/CategorizedProblemService.java | 117 +++++------------- .../AiRequest/AiGenerateProblemFromAiDto.java | 4 + 2 files changed, 36 insertions(+), 85 deletions(-) diff --git a/src/main/java/com/app/domain/categorizedproblem/service/CategorizedProblemService.java b/src/main/java/com/app/domain/categorizedproblem/service/CategorizedProblemService.java index 9308e16..c488021 100644 --- a/src/main/java/com/app/domain/categorizedproblem/service/CategorizedProblemService.java +++ b/src/main/java/com/app/domain/categorizedproblem/service/CategorizedProblemService.java @@ -6,17 +6,21 @@ import com.app.domain.category.service.CategoryService; import com.app.domain.member.entity.Member; import com.app.domain.member.service.MemberService; +import com.app.domain.problem.aigeneratedproblem.dto.ProblemFile.AiRequest.AiGenerateProblemFromAiDto; import com.app.domain.problem.entity.Problem; import com.app.domain.problem.membersavedproblem.dto.MemberSavedProblemDto; import com.app.domain.problem.membersavedproblem.mapper.MemberSavedProblemMapper; import com.app.domain.problem.service.ProblemService; import com.app.domain.summary.membersavedsummary.dto.MemberSavedSummaryDto; +import com.app.global.config.ENUM.PdfType; import com.app.global.config.ENUM.ProblemType; import com.app.global.error.ErrorCode; import com.app.global.error.exception.BusinessException; import com.app.global.error.exception.EntityNotFoundException; import java.io.ByteArrayOutputStream; +import java.io.File; import java.io.IOException; +import java.nio.file.Files; import java.util.ArrayList; import java.util.List; import javax.servlet.http.HttpServletRequest; @@ -32,6 +36,8 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import static com.app.global.pdf.ProblemPdfMaker.CreatePdfFile; + @Service @Transactional @RequiredArgsConstructor @@ -132,101 +138,42 @@ public MemberSavedSummaryDto.pdfResponse createCategorizedProblemsAnswerPdf(Long } } - public MemberSavedSummaryDto.pdfResponse createCategorizedProblemsPdf(Long categoryId) throws IOException { + public MemberSavedSummaryDto.pdfResponse createCategorizedProblemsPdf(Long categoryId){ List categorizedProblemList = categorizedProblemRepository.findByCategoryCategoryId(categoryId); Category category = categoryService.findVerifiedCategoryByCategoryId(categoryId); String title = category.getCategoryName(); - try (PDDocument document = new PDDocument()) { - PDPage page = new PDPage(); - document.addPage(page); - PDPageContentStream contentStream = new PDPageContentStream(document, page); - PDType0Font font = PDType0Font.load(document, getClass().getResourceAsStream("/fonts/malgun.ttf")); - contentStream.setFont(font, 12); - float yPosition = page.getMediaBox().getHeight() - 50; - int linesInCurrentPage = 0; - int maxLinesPerPage = 45; - int problemNumber = 0; // 문제 번호 + // Pdf 생성 DTO 변환 + AiGenerateProblemFromAiDto[] problems = new AiGenerateProblemFromAiDto[categorizedProblemList.size()]; + for(int i = 0; i < categorizedProblemList.size(); i++) { + Problem problem = categorizedProblemList.get(i).getProblem(); + problems[i] = AiGenerateProblemFromAiDto.create( + problem.getProblemName(), + problem.getProblemChoices(), + problem.getProblemAnswer(), + problem.getProblemCommentary() + ); + } - for (CategorizedProblem categorizedProblem : categorizedProblemList) { - problemNumber++; - Problem problem = categorizedProblem.getProblem(); - String problemName = problemNumber + ". " + problem.getProblemName(); + File tempFile = null; + byte[] pdfContent = null; - List problemChoices = new ArrayList<>(); - if (problem.getProblemType() == ProblemType.MULTIPLE) { - problemChoices = problem.getProblemChoices(); - } - float maxWidth = page.getMediaBox().getWidth() - 100; // 페이지 폭에서 양쪽 여백을 뺀 값 - List wrappedProblemName = wrapText(problemName, font, 12, maxWidth); + try { + tempFile = CreatePdfFile(category.getCategoryName(), problems, PdfType.PROBLEM); // Problem PDF 생성 - for (String line : wrappedProblemName) { - if (linesInCurrentPage >= maxLinesPerPage || yPosition < 50) { - contentStream.close(); - page = new PDPage(); - document.addPage(page); - contentStream = new PDPageContentStream(document, page); - contentStream.setFont(font, 12); - yPosition = page.getMediaBox().getHeight() - 50; - linesInCurrentPage = 0; - } + // 파일을 바이트 배열로 변환 + pdfContent = Files.readAllBytes(tempFile.toPath()); - contentStream.beginText(); - contentStream.newLineAtOffset(50, yPosition); - contentStream.showText(line); - contentStream.endText(); - yPosition -= 15; // 줄 간의 간격 - linesInCurrentPage++; - } - yPosition -= 10; // 문제명과 선택지 사이의 간격 조정 - - // 보기 리스트 출력 - if (problemChoices != null) { - char choiceLetter = 'A'; // 선지 번호 (알파벳) - int totalChoices = problemChoices.size(); - - for (String choice : problemChoices) { - List wrappedText = wrapText(choice, font, 12, maxWidth); - boolean isFirstLineOfChoice = true; - - for (String line : wrappedText) { - if (linesInCurrentPage >= maxLinesPerPage || yPosition < 50) { - contentStream.close(); - page = new PDPage(); - document.addPage(page); - contentStream = new PDPageContentStream(document, page); - contentStream.setFont(font, 12); - yPosition = page.getMediaBox().getHeight() - 50; - linesInCurrentPage = 0; - } - - contentStream.beginText(); - contentStream.newLineAtOffset(50, yPosition); - - if (isFirstLineOfChoice) { - contentStream.showText(choiceLetter + ". " + line); // 알파벳 번호 추가 - isFirstLineOfChoice = false; // 첫 줄 출력 후 false로 변경 - } else { - contentStream.showText(line); - } - contentStream.endText(); - yPosition -= 15; - linesInCurrentPage++; - } - if (choiceLetter == 'A' + totalChoices - 1) { // 마지막 선지 확인 - yPosition -= 20; // 마지막 선지 이후에 더 큰 간격 추가 - } - choiceLetter++; // 다음 선지를 위해 알파벳 증가 - } - } + } catch (IOException e) { + throw new BusinessException(ErrorCode.NOT_UPLOAD_PROBLEM); + } finally { + // 임시 파일 삭제 + if (tempFile != null && tempFile.exists()) { + tempFile.delete(); } - - contentStream.close(); - ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); - document.save(byteArrayOutputStream); // 문서를 ByteArrayOutputStream에 저장 - document.close(); // 문서를 닫아 리소스를 해제 - return new MemberSavedSummaryDto.pdfResponse(byteArrayOutputStream.toByteArray(), title); } + + return new MemberSavedSummaryDto.pdfResponse(pdfContent, title); } diff --git a/src/main/java/com/app/domain/problem/aigeneratedproblem/dto/ProblemFile/AiRequest/AiGenerateProblemFromAiDto.java b/src/main/java/com/app/domain/problem/aigeneratedproblem/dto/ProblemFile/AiRequest/AiGenerateProblemFromAiDto.java index fb48dd6..09789f0 100644 --- a/src/main/java/com/app/domain/problem/aigeneratedproblem/dto/ProblemFile/AiRequest/AiGenerateProblemFromAiDto.java +++ b/src/main/java/com/app/domain/problem/aigeneratedproblem/dto/ProblemFile/AiRequest/AiGenerateProblemFromAiDto.java @@ -25,4 +25,8 @@ public class AiGenerateProblemFromAiDto { @Schema(description = "문제 해설", example = "문제 해설 예시") private String problemCommentary; + + public static AiGenerateProblemFromAiDto create(String problemName, List problemChoices, String problemAnswer, String problemCommentary) { + return new AiGenerateProblemFromAiDto(problemName, problemChoices, problemAnswer, problemCommentary); + } } From 2ecadc736314bfd4eb80faadd4efaf7448ef6301 Mon Sep 17 00:00:00 2001 From: yujamint Date: Fri, 26 Jul 2024 00:03:57 +0900 Subject: [PATCH 16/19] feat: CI submodule update --- .github/workflows/test.yaml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 72b3537..3452604 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -17,6 +17,13 @@ jobs: steps: - name: 체크아웃 uses: actions/checkout@v4 + with: + submodules: true + token: ${{ secrets.PERSONAL_ACCESS_TOKEN }} + + - name: 서브모듈 업데이트 + run: | + git submodule update --remote - name: JDK 11 설치 uses: actions/setup-java@v4 From fcdd4487e25b552731b8ea3f53cfdd9402ad74e2 Mon Sep 17 00:00:00 2001 From: Jae Min Yu Date: Fri, 26 Jul 2024 00:12:35 +0900 Subject: [PATCH 17/19] =?UTF-8?q?Revert=20"feat:=20Nginx=20=EB=8F=84?= =?UTF-8?q?=EC=9E=85=20=EB=B0=8F=20=EB=B8=94=EB=A3=A8/=EA=B7=B8=EB=A6=B0?= =?UTF-8?q?=20=EB=AC=B4=EC=A4=91=EB=8B=A8=20=EB=B0=B0=ED=8F=AC=20=EC=A0=81?= =?UTF-8?q?=EC=9A=A9"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/deploy-prod.yaml | 55 ++++-------------------------- build.gradle | 3 -- 2 files changed, 6 insertions(+), 52 deletions(-) diff --git a/.github/workflows/deploy-prod.yaml b/.github/workflows/deploy-prod.yaml index db5872e..825c94f 100644 --- a/.github/workflows/deploy-prod.yaml +++ b/.github/workflows/deploy-prod.yaml @@ -53,53 +53,10 @@ jobs: host: ${{ secrets.PROD_SERVER_HOST }} username: ${{ secrets.PROD_SERVER_USERNAME }} key: ${{ secrets.PROD_SERVER_PEM_KEY }} - envs: GITHUB_SHA, DOCKERHUB_USERNAME + envs: GITHUB_SHA script: | - # 현재 활성화된 Nginx 설정 파일 확인 - CURRENT_CONF=$(sudo readlink /etc/nginx/sites-enabled/current) - echo "Current Nginx configuration: $CURRENT_CONF" - if [[ "$CURRENT_CONF" == *"blue" ]]; then - NEW_CONF="/etc/nginx/sites-available/green" - OLD_CONTAINER="blue-container" - NEW_CONTAINER="green-container" - NEW_PORT=8081 - else - NEW_CONF="/etc/nginx/sites-available/blue" - OLD_CONTAINER="green-container" - NEW_CONTAINER="blue-container" - NEW_PORT=8080 - fi - - echo "New Nginx configuration: $NEW_CONF" - echo "Old container: $OLD_CONTAINER" - echo "New container: $NEW_CONTAINER" - echo "New port: $NEW_PORT" - - # 새 Docker 이미지 가져오기 - sudo docker pull ${{ secrets.DOCKERHUB_USERNAME }}/qtudy-server:prod - - # 새로운 컨테이너 실행 - sudo docker run -d -p $NEW_PORT:8080 --name $NEW_CONTAINER ${{ secrets.DOCKERHUB_USERNAME }}/qtudy-server:prod - - # 새로운 컨테이너가 준비될 때까지 대기 - echo "Waiting for the new container to be ready..." - sleep 10 - - # 헬스 체크를 통해 새 컨테이너가 정상적으로 실행 중인지 확인 - until [[ "$(curl -s -o /dev/null -w ''%{http_code}'' http://localhost:$NEW_PORT/actuator/health)" == "200" ]]; do - echo "Waiting for the new container to respond with HTTP 200..." - sleep 2 - done - - echo "New container is ready. Switching Nginx configuration." - - # Nginx 설정 파일 교체 및 재시작 - sudo ln -sf $NEW_CONF /etc/nginx/sites-enabled/current - sudo systemctl reload nginx - - # 이전 컨테이너 중지 및 제거 - sudo docker stop $OLD_CONTAINER - sudo docker rm $OLD_CONTAINER - - # 사용하지 않는 Docker 이미지 정리 - sudo docker image prune -f \ No newline at end of file + sudo docker stop $(sudo docker ps -a -q) + sudo docker rm $(sudo docker ps -a -q) + sudo docker pull ${{secrets.DOCKERHUB_USERNAME}}/qtudy-server:prod + sudo docker run -d -p 8080:8080 --name qtudy-server-container ${{secrets.DOCKERHUB_USERNAME}}/qtudy-server:prod + sudo docker image prune -f diff --git a/build.gradle b/build.gradle index 0a2a3d4..90dbf9e 100644 --- a/build.gradle +++ b/build.gradle @@ -49,9 +49,6 @@ dependencies { implementation 'org.mapstruct:mapstruct:1.5.3.Final' annotationProcessor 'org.mapstruct:mapstruct-processor:1.5.3.Final' - // Spring Boot Actuator - implementation 'org.springframework.boot:spring-boot-starter-actuator' - // GPT 스크립트 테스트 편의성을 위해 추가 testAnnotationProcessor 'org.projectlombok:lombok' testImplementation 'com.theokanning.openai-gpt3-java:service:0.18.2' From 047d1def627ac010ff2ffe4b156d1af1e90122c6 Mon Sep 17 00:00:00 2001 From: yujamint Date: Fri, 26 Jul 2024 00:18:51 +0900 Subject: [PATCH 18/19] =?UTF-8?q?Revert=20"Revert=20"feat:=20Nginx=20?= =?UTF-8?q?=EB=8F=84=EC=9E=85=20=EB=B0=8F=20=EB=B8=94=EB=A3=A8/=EA=B7=B8?= =?UTF-8?q?=EB=A6=B0=20=EB=AC=B4=EC=A4=91=EB=8B=A8=20=EB=B0=B0=ED=8F=AC=20?= =?UTF-8?q?=EC=A0=81=EC=9A=A9""?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit fcdd4487e25b552731b8ea3f53cfdd9402ad74e2. --- .github/workflows/deploy-prod.yaml | 55 ++++++++++++++++++++++++++---- build.gradle | 3 ++ 2 files changed, 52 insertions(+), 6 deletions(-) diff --git a/.github/workflows/deploy-prod.yaml b/.github/workflows/deploy-prod.yaml index 825c94f..db5872e 100644 --- a/.github/workflows/deploy-prod.yaml +++ b/.github/workflows/deploy-prod.yaml @@ -53,10 +53,53 @@ jobs: host: ${{ secrets.PROD_SERVER_HOST }} username: ${{ secrets.PROD_SERVER_USERNAME }} key: ${{ secrets.PROD_SERVER_PEM_KEY }} - envs: GITHUB_SHA + envs: GITHUB_SHA, DOCKERHUB_USERNAME script: | - sudo docker stop $(sudo docker ps -a -q) - sudo docker rm $(sudo docker ps -a -q) - sudo docker pull ${{secrets.DOCKERHUB_USERNAME}}/qtudy-server:prod - sudo docker run -d -p 8080:8080 --name qtudy-server-container ${{secrets.DOCKERHUB_USERNAME}}/qtudy-server:prod - sudo docker image prune -f + # 현재 활성화된 Nginx 설정 파일 확인 + CURRENT_CONF=$(sudo readlink /etc/nginx/sites-enabled/current) + echo "Current Nginx configuration: $CURRENT_CONF" + if [[ "$CURRENT_CONF" == *"blue" ]]; then + NEW_CONF="/etc/nginx/sites-available/green" + OLD_CONTAINER="blue-container" + NEW_CONTAINER="green-container" + NEW_PORT=8081 + else + NEW_CONF="/etc/nginx/sites-available/blue" + OLD_CONTAINER="green-container" + NEW_CONTAINER="blue-container" + NEW_PORT=8080 + fi + + echo "New Nginx configuration: $NEW_CONF" + echo "Old container: $OLD_CONTAINER" + echo "New container: $NEW_CONTAINER" + echo "New port: $NEW_PORT" + + # 새 Docker 이미지 가져오기 + sudo docker pull ${{ secrets.DOCKERHUB_USERNAME }}/qtudy-server:prod + + # 새로운 컨테이너 실행 + sudo docker run -d -p $NEW_PORT:8080 --name $NEW_CONTAINER ${{ secrets.DOCKERHUB_USERNAME }}/qtudy-server:prod + + # 새로운 컨테이너가 준비될 때까지 대기 + echo "Waiting for the new container to be ready..." + sleep 10 + + # 헬스 체크를 통해 새 컨테이너가 정상적으로 실행 중인지 확인 + until [[ "$(curl -s -o /dev/null -w ''%{http_code}'' http://localhost:$NEW_PORT/actuator/health)" == "200" ]]; do + echo "Waiting for the new container to respond with HTTP 200..." + sleep 2 + done + + echo "New container is ready. Switching Nginx configuration." + + # Nginx 설정 파일 교체 및 재시작 + sudo ln -sf $NEW_CONF /etc/nginx/sites-enabled/current + sudo systemctl reload nginx + + # 이전 컨테이너 중지 및 제거 + sudo docker stop $OLD_CONTAINER + sudo docker rm $OLD_CONTAINER + + # 사용하지 않는 Docker 이미지 정리 + sudo docker image prune -f \ No newline at end of file diff --git a/build.gradle b/build.gradle index 90dbf9e..0a2a3d4 100644 --- a/build.gradle +++ b/build.gradle @@ -49,6 +49,9 @@ dependencies { implementation 'org.mapstruct:mapstruct:1.5.3.Final' annotationProcessor 'org.mapstruct:mapstruct-processor:1.5.3.Final' + // Spring Boot Actuator + implementation 'org.springframework.boot:spring-boot-starter-actuator' + // GPT 스크립트 테스트 편의성을 위해 추가 testAnnotationProcessor 'org.projectlombok:lombok' testImplementation 'com.theokanning.openai-gpt3-java:service:0.18.2' From e93f2a9034cb620f349560b8d6d8c62b720fbcfa Mon Sep 17 00:00:00 2001 From: yujamint Date: Fri, 26 Jul 2024 00:24:14 +0900 Subject: [PATCH 19/19] feat: cache annotation --- .../categorizedproblem/service/CategorizedProblemService.java | 2 +- .../categorizedsummary/service/CategorizedSummaryService.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/app/domain/categorizedproblem/service/CategorizedProblemService.java b/src/main/java/com/app/domain/categorizedproblem/service/CategorizedProblemService.java index 139bef4..e90dcea 100644 --- a/src/main/java/com/app/domain/categorizedproblem/service/CategorizedProblemService.java +++ b/src/main/java/com/app/domain/categorizedproblem/service/CategorizedProblemService.java @@ -186,7 +186,7 @@ public CategorizedProblem updateCategorizedProblem(Long categorizedProblemId, Me } @Transactional(readOnly = true) -// @Cacheable(value = "categorizedProblem", key = "#categoryId") + @Cacheable(value = "categorizedProblem", key = "#categoryId") public Page findCategorizedProblemsByCategoryId(Long categoryId, int page, int size) { PageRequest pageRequest = PageRequest.of(page, size); return categorizedProblemRepository.findByCategoryCategoryId(categoryId, pageRequest); diff --git a/src/main/java/com/app/domain/categorizedsummary/service/CategorizedSummaryService.java b/src/main/java/com/app/domain/categorizedsummary/service/CategorizedSummaryService.java index c690917..6d38c2c 100644 --- a/src/main/java/com/app/domain/categorizedsummary/service/CategorizedSummaryService.java +++ b/src/main/java/com/app/domain/categorizedsummary/service/CategorizedSummaryService.java @@ -111,7 +111,7 @@ public CategorizedSummary findVerifiedCategorizedSummaryByCategorizedSummaryId(L } @Transactional(readOnly = true) -// @Cacheable(value = "categorizedSummary", key = "#categoryId") + @Cacheable(value = "categorizedSummary", key = "#categoryId") public Page findCategorziedSummarysByCategoryId(Long categoryId, int page, int size) { PageRequest pageRequest = PageRequest.of(page, size); return categorizedSummaryRepository.findByCategoryCategoryId(categoryId, pageRequest);