From 4e18178caf82efdd7667aad4af0b7ce2de4eab2c Mon Sep 17 00:00:00 2001 From: Youth <109585620+Youthhing@users.noreply.github.com> Date: Tue, 28 May 2024 13:50:35 +0900 Subject: [PATCH 01/14] Chore: update code-deploy-app-name (#6) --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c314c84f..121d83cd 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -7,7 +7,7 @@ on: env: PROJECT_NAME: COTATO-BE-TEST BUCKET_NAME: cotato-ci-cd-bucket-test - CODE_DEPLOY_APP_NAME: cotato-deploy-test + CODE_DEPLOY_APP_NAME: cotato-deploy DEPLOYMENT_GROUP_NAME: cotato-deploy-group-test RESOURCE_PATH: ./src/main/resources/application-stage.yml From 728b339e51a74c0ac5d9bc9ca7e12ae0855633c7 Mon Sep 17 00:00:00 2001 From: youth Date: Tue, 28 May 2024 14:17:22 +0900 Subject: [PATCH 02/14] Chore: set overwrite --- appspec.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/appspec.yml b/appspec.yml index b1b420fb..1d02e5eb 100644 --- a/appspec.yml +++ b/appspec.yml @@ -5,6 +5,7 @@ files: - source: / destination: /home/ubuntu/backend/CS-Quiz-BE overwrite: yes +file_exists_behavior: OVERWRITE permissions: - object: / From 5ead4dbd10ebf6ed0ce4737b4bf6263edff3fc0e Mon Sep 17 00:00:00 2001 From: Youth <109585620+Youthhing@users.noreply.github.com> Date: Tue, 28 May 2024 14:28:41 +0900 Subject: [PATCH 03/14] =?UTF-8?q?Chore:=20=EB=B0=B0=ED=8F=AC=20=EC=8A=A4?= =?UTF-8?q?=ED=81=AC=EB=A6=BD=ED=8A=B8=20=EB=B6=84=EA=B8=B0=20=EB=A1=9C?= =?UTF-8?q?=EA=B7=B8=20=EC=B6=94=EA=B0=80=20(#7)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Chore: update code-deploy-app-name * Chore: set overwrite * Chore: 배포 스크립트 분기 로그 추가 --- scripts/deploy.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/scripts/deploy.sh b/scripts/deploy.sh index 8b1fd8ef..337d74f3 100644 --- a/scripts/deploy.sh +++ b/scripts/deploy.sh @@ -11,11 +11,14 @@ if [ "$CURRENT_BRANCH" == "main" ]; then PROFILE="prod" DIRECTORY="production" PORT=8080 + echo "현재 브랜치: '$CURRENT_BRANCH'" elif [ "$CURRENT_BRANCH" == "release" ]; then PROFILE="stage" DIRECTORY="release" PORT=8082 + echo "현재 브랜치: '$CURRENT_BRANCH'" else + echo "현재 브랜치: '$CURRENT_BRANCH'" echo "지원되지 않는 브랜치입니다: $CURRENT_BRANCH" >&2 exit 1 fi From 38ccd01bc3ff8500e497b41e802d3725d1ea9a8a Mon Sep 17 00:00:00 2001 From: Youth <109585620+Youthhing@users.noreply.github.com> Date: Tue, 28 May 2024 14:42:13 +0900 Subject: [PATCH 04/14] =?UTF-8?q?Chore:=20=EB=B8=8C=EB=9E=9C=EC=B9=98?= =?UTF-8?q?=EB=AA=85=20=ED=99=95=EC=9D=B8=EC=9D=84=20=EC=9C=84=ED=95=9C=20?= =?UTF-8?q?=EC=8A=A4=ED=81=AC=EB=A6=BD=ED=8A=B8=20=EA=B2=BD=EB=A1=9C=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20(#8)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Chore: update code-deploy-app-name * Chore: set overwrite * Chore: 배포 스크립트 분기 로그 추가 * Chore: 브랜치 확인을 위한 경로 이동 스크립트 추가 --- scripts/deploy.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/scripts/deploy.sh b/scripts/deploy.sh index 337d74f3..ffec9057 100644 --- a/scripts/deploy.sh +++ b/scripts/deploy.sh @@ -1,5 +1,8 @@ #!/bin/bash +# .git repo가 존재하는 곳으로 이동 +cd /home/ubuntu/backend/CS-Quiz-BE || { echo "Failed to change directory to git root"; exit 1; } + # 현재 브랜치 이름 가져오기 CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD) From 30e8250ebc346deb6c6b974f970a5878849a0b30 Mon Sep 17 00:00:00 2001 From: Youth <109585620+Youthhing@users.noreply.github.com> Date: Tue, 28 May 2024 14:52:20 +0900 Subject: [PATCH 05/14] =?UTF-8?q?Chore:=20=EC=9E=91=EC=97=85=20=EB=94=94?= =?UTF-8?q?=EB=A0=89=ED=86=A0=EB=A6=AC=20=EC=8B=A0=EB=A2=B0=EB=A5=BC=20?= =?UTF-8?q?=EC=9C=84=ED=95=9C=20Git=20=EC=84=A4=EC=A0=95=20(#9)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Chore: update code-deploy-app-name * Chore: set overwrite * Chore: 배포 스크립트 분기 로그 추가 * Chore: 브랜치 확인을 위한 경로 이동 스크립트 추가 * Chore: 작업 디렉토리 신뢰를 위한 git 설정 --- scripts/deploy.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/scripts/deploy.sh b/scripts/deploy.sh index ffec9057..b99c4eec 100644 --- a/scripts/deploy.sh +++ b/scripts/deploy.sh @@ -1,5 +1,8 @@ #!/bin/bash +# Git이 디렉토리를 안전한 디렉토리로 인식하도록 설정 +git config --global --add safe.directory /home/ubuntu/backend/CS-Quiz-BE + # .git repo가 존재하는 곳으로 이동 cd /home/ubuntu/backend/CS-Quiz-BE || { echo "Failed to change directory to git root"; exit 1; } From 5590919c44dfcce0fd1d11026894c751e884ac36 Mon Sep 17 00:00:00 2001 From: Youth <109585620+Youthhing@users.noreply.github.com> Date: Tue, 28 May 2024 15:25:19 +0900 Subject: [PATCH 06/14] =?UTF-8?q?Chore:=20JAR=ED=8C=8C=EC=9D=BC=20?= =?UTF-8?q?=EA=B2=BD=EB=A1=9C=20=ED=99=95=EC=9D=B8=EC=9D=84=20=EC=9C=84?= =?UTF-8?q?=ED=95=9C=20=EC=99=80=EC=9D=BC=EB=93=9C=EC=B9=B4=EB=93=9C=20?= =?UTF-8?q?=EC=84=A4=EC=A0=95=20(#10)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Chore: update code-deploy-app-name * Chore: set overwrite * Chore: 배포 스크립트 분기 로그 추가 * Chore: 브랜치 확인을 위한 경로 이동 스크립트 추가 * Chore: 작업 디렉토리 신뢰를 위한 git 설정 * Chore: jar파일 경로 구체화 --- scripts/deploy.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/deploy.sh b/scripts/deploy.sh index b99c4eec..e16c3617 100644 --- a/scripts/deploy.sh +++ b/scripts/deploy.sh @@ -29,7 +29,7 @@ else exit 1 fi -JAR_PATH="/home/ubuntu/backend/$PROJECT_NAME/build/libs/*$PROFILE.jar" +JAR_PATH="/home/ubuntu/backend/$PROJECT_NAME/build/libs/*$PROFILE*.jar" DEPLOY_PATH=/home/ubuntu/backend/$DIRECTORY/$PROJECT_NAME/ #jar 파일이 복사되고 실행될 경로 DEPLOY_LOG_PATH="/home/ubuntu/backend/$DIRECTORY/log/deploy/$PROJECT_NAME/deploy_$(date +%Y%m%d).log" DEPLOY_ERR_LOG_PATH="/home/ubuntu/backend/$DIRECTORY/log/deploy/$PROJECT_NAME/deploy_err_$(date +%Y%m%d).log" From 37d553158e43b853b1e132324bb1f8ad93ee449d Mon Sep 17 00:00:00 2001 From: Youth <109585620+Youthhing@users.noreply.github.com> Date: Tue, 28 May 2024 16:43:25 +0900 Subject: [PATCH 07/14] =?UTF-8?q?Chore:=20JAR=ED=8C=8C=EC=9D=BC=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=20=EC=A0=84=20=EB=B9=8C=EB=93=9C=20=EC=9E=91?= =?UTF-8?q?=EC=97=85=EC=9D=84=20=EC=B6=94=EA=B0=80=20(#11)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Chore: update code-deploy-app-name * Chore: set overwrite * Chore: 배포 스크립트 분기 로그 추가 * Chore: 브랜치 확인을 위한 경로 이동 스크립트 추가 * Chore: 작업 디렉토리 신뢰를 위한 git 설정 * Chore: jar파일 경로 구체화 * Chore: jar파일 생성 전 build를 선행 작업으로 추가 --- build.gradle | 2 ++ 1 file changed, 2 insertions(+) diff --git a/build.gradle b/build.gradle index 29897875..d9fb7421 100644 --- a/build.gradle +++ b/build.gradle @@ -55,11 +55,13 @@ jar { } task stageJar(type: Jar) { + dependsOn 'build' archiveBaseName.set("${project.name}-stage") from sourceSets.main.output } task prodJar(type: Jar) { + dependsOn 'build' archiveBaseName.set("${project.name}-prod") from sourceSets.main.output } From 15278abb7a1fa21da05301084595ea7cd0c45e55 Mon Sep 17 00:00:00 2001 From: Youth <109585620+Youthhing@users.noreply.github.com> Date: Tue, 28 May 2024 17:09:01 +0900 Subject: [PATCH 08/14] =?UTF-8?q?Chore:=20=EB=B9=8C=EB=93=9C=20=ED=9B=84?= =?UTF-8?q?=20JAR=ED=8C=8C=EC=9D=BC=EC=9D=98=20=EC=9D=B4=EB=A6=84=EC=9D=84?= =?UTF-8?q?=20=EB=B3=80=EA=B2=BD=ED=95=98=EB=8A=94=20=EB=B0=A9=EC=8B=9D=20?= =?UTF-8?q?=EC=B1=84=ED=83=9D=20(#12)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Chore: update code-deploy-app-name * Chore: set overwrite * Chore: 배포 스크립트 분기 로그 추가 * Chore: 브랜치 확인을 위한 경로 이동 스크립트 추가 * Chore: 작업 디렉토리 신뢰를 위한 git 설정 * Chore: jar파일 경로 구체화 * Chore: jar파일 생성 전 build를 선행 작업으로 추가 * Chore: 정상 build 후 JAR파일 이름을 변경하는 방식으로 수정 --- .github/workflows/deploy.yml | 7 ++++++- .github/workflows/release.yml | 7 ++++++- build.gradle | 12 ------------ 3 files changed, 12 insertions(+), 14 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 07db760d..5cdc5c3b 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -51,7 +51,12 @@ jobs: # [3] 프로젝트 빌드 - name: Build with Gradle Wrapper - run: ./gradlew prodJar + run: ./gradlew build + + # [3] - 1 생성된 jar 파일 이름 변경 + - name: Rename JAR file + run: mv build/libs/*.jar build/libs/csquiz-prod-0.0.1-SNAPSHOT.jar + shell: bash # [4] Zip 파일 만들기 - name: Make Zip File diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 121d83cd..35e22d2f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -51,7 +51,12 @@ jobs: # [3] 프로젝트 빌드 - name: Build with Gradle Wrapper - run: ./gradlew stageJar + run: ./gradlew build + + # [3] - 1 생성된 jar 파일 이름 변경 + - name: Rename JAR file + run: mv build/libs/*.jar build/libs/csquiz-stage-0.0.1-SNAPSHOT.jar + shell: bash # [4] Zip 파일 만들기 - name: Make Zip File diff --git a/build.gradle b/build.gradle index d9fb7421..b7baea0a 100644 --- a/build.gradle +++ b/build.gradle @@ -53,15 +53,3 @@ tasks.named('test') { jar { enabled = false } - -task stageJar(type: Jar) { - dependsOn 'build' - archiveBaseName.set("${project.name}-stage") - from sourceSets.main.output -} - -task prodJar(type: Jar) { - dependsOn 'build' - archiveBaseName.set("${project.name}-prod") - from sourceSets.main.output -} From 2276ea1393f4ebe3e25ec2ea96422e185be6b748 Mon Sep 17 00:00:00 2001 From: Youth <109585620+Youthhing@users.noreply.github.com> Date: Tue, 28 May 2024 17:17:32 +0900 Subject: [PATCH 09/14] =?UTF-8?q?Chore:=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=84=9C=EB=B2=84=20jdbc=20url=20=EC=88=98=EC=A0=95=20(#13)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Chore: update code-deploy-app-name * Chore: set overwrite * Chore: 배포 스크립트 분기 로그 추가 * Chore: 브랜치 확인을 위한 경로 이동 스크립트 추가 * Chore: 작업 디렉토리 신뢰를 위한 git 설정 * Chore: jar파일 경로 구체화 * Chore: jar파일 생성 전 build를 선행 작업으로 추가 * Chore: 정상 build 후 JAR파일 이름을 변경하는 방식으로 수정 * Chore: test server jdbc url 수정 --- src/main/resources/application-stage.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/application-stage.yml b/src/main/resources/application-stage.yml index 8d1d48c1..c699cccb 100644 --- a/src/main/resources/application-stage.yml +++ b/src/main/resources/application-stage.yml @@ -6,7 +6,7 @@ server: spring: jpa: hibernate: - ddl-auto: ${TEST_DDL_AUTO} + ddl-auto: jdbc:mysql://${TEST_DDL_AUTO} show_sql: true properties: hibernate: From 043c1adb3a5e3d3e1ededd44f3410d16ef768fe1 Mon Sep 17 00:00:00 2001 From: Youth <109585620+Youthhing@users.noreply.github.com> Date: Tue, 28 May 2024 17:32:21 +0900 Subject: [PATCH 10/14] =?UTF-8?q?Fix:=20DDL=5FAUTO=20=EC=98=A4=ED=83=80=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20(#14)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Chore: update code-deploy-app-name * Chore: set overwrite * Chore: 배포 스크립트 분기 로그 추가 * Chore: 브랜치 확인을 위한 경로 이동 스크립트 추가 * Chore: 작업 디렉토리 신뢰를 위한 git 설정 * Chore: jar파일 경로 구체화 * Chore: jar파일 생성 전 build를 선행 작업으로 추가 * Chore: 정상 build 후 JAR파일 이름을 변경하는 방식으로 수정 * Chore: test server jdbc url 수정 * Chore: test server jdbc url 수정 From 324029d9ce09089b97faab6b6d1bcdd6b87b7eae Mon Sep 17 00:00:00 2001 From: Youth <109585620+Youthhing@users.noreply.github.com> Date: Tue, 28 May 2024 17:59:02 +0900 Subject: [PATCH 11/14] =?UTF-8?q?Chore:=20Github=20Actions=EC=97=90=20?= =?UTF-8?q?=ED=82=A4=EB=A5=BC=20=EC=A3=BC=EC=9E=85=ED=95=98=EB=8A=94=20?= =?UTF-8?q?=EB=B0=A9=EC=8B=9D=20=EB=B3=80=EA=B2=BD=20(#15)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Chore: update code-deploy-app-name * Chore: set overwrite * Chore: 배포 스크립트 분기 로그 추가 * Chore: 브랜치 확인을 위한 경로 이동 스크립트 추가 * Chore: 작업 디렉토리 신뢰를 위한 git 설정 * Chore: jar파일 경로 구체화 * Chore: jar파일 생성 전 build를 선행 작업으로 추가 * Chore: 정상 build 후 JAR파일 이름을 변경하는 방식으로 수정 * Chore: test server jdbc url 수정 * Chore: test server jdbc url 수정 * Chore: Github action에 키를 주입하는 방식 변경 --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 35e22d2f..66837a1f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -36,7 +36,7 @@ jobs: spring.jpa.hibernate.ddl-auto: ${{ secrets.TEST_DDL_AUTO }} spring.mail.username: ${{ secrets.SENDER_EMAIL }} spring.mail.password: ${{ secrets.SENDER_PASSWORD }} - jwt.secretKey: ${{ secrets.JWT_SECRET_KEY}} + JWT_SECRET_KEY: ${{ secrets.JWT_SECRET_KEY}} cloud.aws.s3.bucket: ${{ secrets.S3_BUCKET_NAME }} cloud.aws.credentials.accessKey: ${{ secrets.S3_ACCESS_KEY }} cloud.aws.credentials.secretKey: ${{ secrets.S3_ACCESS_PASSWORD }} From ffa8d1ec935b99db32d3bf3414a170fa16abc3b0 Mon Sep 17 00:00:00 2001 From: Youth <109585620+Youthhing@users.noreply.github.com> Date: Tue, 28 May 2024 18:17:22 +0900 Subject: [PATCH 12/14] =?UTF-8?q?Chore:=20=EA=B8=B0=EB=B3=B8=20Yaml=20?= =?UTF-8?q?=ED=8C=8C=EC=9D=BC=20=ED=99=98=EA=B2=BD=20=EB=B3=80=EC=88=98=20?= =?UTF-8?q?=EC=84=B8=ED=8C=85=20=EA=B3=BC=EC=A0=95=20=EC=B6=94=EA=B0=80=20?= =?UTF-8?q?(#16)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Chore: update code-deploy-app-name * Chore: set overwrite * Chore: 배포 스크립트 분기 로그 추가 * Chore: 브랜치 확인을 위한 경로 이동 스크립트 추가 * Chore: 작업 디렉토리 신뢰를 위한 git 설정 * Chore: jar파일 경로 구체화 * Chore: jar파일 생성 전 build를 선행 작업으로 추가 * Chore: 정상 build 후 JAR파일 이름을 변경하는 방식으로 수정 * Chore: test server jdbc url 수정 * Chore: test server jdbc url 수정 * Chore: Github action에 키를 주입하는 방식 변경 * Chore: application.yml 환경 변수 세팅 단계 추가 --- .github/workflows/deploy.yml | 8 ++++++++ .github/workflows/release.yml | 11 ++++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 5cdc5c3b..8dcc1c5d 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -10,6 +10,7 @@ env: CODE_DEPLOY_APP_NAME: cotato-deploy DEPLOYMENT_GROUP_NAME: cotato-deploy-group RESOURCE_PATH: ./src/main/resources/application-prod.yml + BASE_RESOURCE_PATH: ./src/main/resource/application.yml jobs: build: @@ -36,6 +37,13 @@ jobs: spring.jpa.hibernate.ddl-auto: ${{ secrets.DDL_AUTO }} spring.mail.username: ${{ secrets.SENDER_EMAIL }} spring.mail.password: ${{ secrets.SENDER_PASSWORD }} + + # application-yml을 세팅한다. + - name: Set up Base Yaml File + uses: microsoft/variable-substitution@v1 + with: + files: ${{ env.BASE_RESOURCE_PATH }} + env: jwt.secretKey: ${{ secrets.JWT_SECRET_KEY}} cloud.aws.s3.bucket: ${{ secrets.S3_BUCKET_NAME }} cloud.aws.credentials.accessKey: ${{ secrets.S3_ACCESS_KEY }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 66837a1f..eb886793 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -10,6 +10,7 @@ env: CODE_DEPLOY_APP_NAME: cotato-deploy DEPLOYMENT_GROUP_NAME: cotato-deploy-group-test RESOURCE_PATH: ./src/main/resources/application-stage.yml + BASE_RESOURCE_PATH: ./src/main/resource/application.yml jobs: build: @@ -25,6 +26,7 @@ jobs: distribution: 'zulu' # [1] Set up Yaml File + # application-stage.yml을 세팅한다. - name: Set up Yaml File uses: microsoft/variable-substitution@v1 with: @@ -36,7 +38,14 @@ jobs: spring.jpa.hibernate.ddl-auto: ${{ secrets.TEST_DDL_AUTO }} spring.mail.username: ${{ secrets.SENDER_EMAIL }} spring.mail.password: ${{ secrets.SENDER_PASSWORD }} - JWT_SECRET_KEY: ${{ secrets.JWT_SECRET_KEY}} + + # application.yml을 세팅한다. + - name: Set up Base Yaml File + uses: microsoft/variable-substitution@v1 + with: + files: ${{ env.BASE_RESOURCE_PATH }} + env: + jwt.secretKey: ${{ secrets.JWT_SECRET_KEY}} cloud.aws.s3.bucket: ${{ secrets.S3_BUCKET_NAME }} cloud.aws.credentials.accessKey: ${{ secrets.S3_ACCESS_KEY }} cloud.aws.credentials.secretKey: ${{ secrets.S3_ACCESS_PASSWORD }} From a1356ce9bf14efb31a921b7f383a1e9408317010 Mon Sep 17 00:00:00 2001 From: Youth <109585620+Youthhing@users.noreply.github.com> Date: Tue, 28 May 2024 18:21:12 +0900 Subject: [PATCH 13/14] =?UTF-8?q?Chore:=20yaml=20=ED=8C=8C=EC=9D=BC=20?= =?UTF-8?q?=EC=84=B8=ED=8C=85=20=EA=B3=BC=EC=A0=95=20=EC=98=A4=ED=83=80=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20(#17)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Chore: update code-deploy-app-name * Chore: set overwrite * Chore: 배포 스크립트 분기 로그 추가 * Chore: 브랜치 확인을 위한 경로 이동 스크립트 추가 * Chore: 작업 디렉토리 신뢰를 위한 git 설정 * Chore: jar파일 경로 구체화 * Chore: jar파일 생성 전 build를 선행 작업으로 추가 * Chore: 정상 build 후 JAR파일 이름을 변경하는 방식으로 수정 * Chore: test server jdbc url 수정 * Chore: test server jdbc url 수정 * Chore: Github action에 키를 주입하는 방식 변경 * Chore: application.yml 환경 변수 세팅 단계 추가 * Chore: application.yml 환경 변수 세팅 단계 추가 --- .github/workflows/deploy.yml | 2 +- .github/workflows/release.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 8dcc1c5d..cb5513c0 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -10,7 +10,7 @@ env: CODE_DEPLOY_APP_NAME: cotato-deploy DEPLOYMENT_GROUP_NAME: cotato-deploy-group RESOURCE_PATH: ./src/main/resources/application-prod.yml - BASE_RESOURCE_PATH: ./src/main/resource/application.yml + BASE_RESOURCE_PATH: ./src/main/resources/application.yml jobs: build: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index eb886793..83843098 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -10,7 +10,7 @@ env: CODE_DEPLOY_APP_NAME: cotato-deploy DEPLOYMENT_GROUP_NAME: cotato-deploy-group-test RESOURCE_PATH: ./src/main/resources/application-stage.yml - BASE_RESOURCE_PATH: ./src/main/resource/application.yml + BASE_RESOURCE_PATH: ./src/main/resources/application.yml jobs: build: From 2a5c59cd163f27652604f978a86bec15177e0cdf Mon Sep 17 00:00:00 2001 From: Youth <109585620+Youthhing@users.noreply.github.com> Date: Thu, 30 May 2024 17:29:31 +0900 Subject: [PATCH 14/14] =?UTF-8?q?Feature:=20=EA=B5=90=EC=9C=A1=20=EA=B2=B0?= =?UTF-8?q?=EC=8A=B9=EC=A7=84=EC=B6=9C=EC=9E=90,=20=EC=9A=B0=EC=8A=B9?= =?UTF-8?q?=EC=9E=90=20=EA=B3=84=EC=82=B0,=20=EC=9E=AC=EC=A0=84=EC=86=A1?= =?UTF-8?q?=20API=20=EA=B5=AC=ED=98=84=20=20(#19)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Chore: update code-deploy-app-name * Chore: set overwrite * Chore: 배포 스크립트 분기 로그 추가 * Chore: 브랜치 확인을 위한 경로 이동 스크립트 추가 * Chore: 작업 디렉토리 신뢰를 위한 git 설정 * Chore: jar파일 경로 구체화 * Chore: jar파일 생성 전 build를 선행 작업으로 추가 * Chore: 정상 build 후 JAR파일 이름을 변경하는 방식으로 수정 * Chore: test server jdbc url 수정 * Chore: test server jdbc url 수정 * Chore: Github action에 키를 주입하는 방식 변경 * Chore: application.yml 환경 변수 세팅 단계 추가 * Chore: application.yml 환경 변수 세팅 단계 추가 * docs: Update Feature Issue Template * docs: Update Fix Issue Template * docs: PR 템플릿 생성 * docs: PR 템플릿 이모지 제거 * Feature: 교육 결승진출자, 우승자 계산, 재전송 API 구현 (#3) * feat: 교육 결승진출자 계산, 재전송 API 구현 * feat: 교육 결승진출자 계산, 재전송 API 구현 * feat: kingking member, winner 계산 + 전송 API 구현 * feat: 이미 우승자가 계산됐으면 exception 발생 * refactor: 코드 리뷰를 기반으로 코드 수정 * refactor: 컨트롤러, 서비스 메소드 위치 변경 --------- Co-authored-by: GiHun Nam <52378919+gikhoon@users.noreply.github.com> --- .../ISSUE_TEMPLATE/feature-issue-template.md | 22 +++++ .github/ISSUE_TEMPLATE/fix-issue-template.md | 28 +++++++ .github/pull_request_template.md | 9 +++ .../controller/EducationController.java | 24 +++++- .../socket/controller/SocketController.java | 16 ++++ .../socket/dto/EducationResultResponse.java | 13 +++ .../api/socket/dto/QuizStopResponse.java | 6 +- .../cotato/csquiz/common/error/ErrorCode.java | 4 + .../common/websocket/WebSocketHandler.java | 22 +++-- .../repository/KingMemberRepository.java | 2 + .../education/repository/QuizRepository.java | 5 ++ .../repository/WinnerRepository.java | 2 + .../education/service/EducationService.java | 29 ------- .../education/service/KingMemberService.java | 80 ++++++++++++++----- .../education/service/SocketService.java | 25 +++--- 15 files changed, 217 insertions(+), 70 deletions(-) create mode 100644 .github/ISSUE_TEMPLATE/feature-issue-template.md create mode 100644 .github/ISSUE_TEMPLATE/fix-issue-template.md create mode 100644 .github/pull_request_template.md create mode 100644 src/main/java/org/cotato/csquiz/api/socket/dto/EducationResultResponse.java diff --git a/.github/ISSUE_TEMPLATE/feature-issue-template.md b/.github/ISSUE_TEMPLATE/feature-issue-template.md new file mode 100644 index 00000000..6aeb303d --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature-issue-template.md @@ -0,0 +1,22 @@ +--- +name: Feature Issue Template +about: Feature 브랜치 생성 전 작성해주세요 +title: "[Feature]" +labels: '' +assignees: '' + +--- + +## 🪶 추가할 기능 설명 + + +## ✅ 작업 내용 + +- [ ] 구현 내용 1 +- [ ] 구현 내용 2 + +## 스크린샷 (선택) + +## 🔗 참고한 링크 (선택) + +## ETC diff --git a/.github/ISSUE_TEMPLATE/fix-issue-template.md b/.github/ISSUE_TEMPLATE/fix-issue-template.md new file mode 100644 index 00000000..d36e7632 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/fix-issue-template.md @@ -0,0 +1,28 @@ +--- +name: Fix Issue Template +about: Fix 브랜치 생성 전 작성해주세요 +title: "[Fix]" +labels: '' +assignees: '' + +--- + +## ⚠️ 발생한 에러 + + +## 에러가 발생한 상황 + +**Given** : +**When** : +**Then** : + +## ✅ 수정한 내용 + +- [ ] 수정 내용 1 +- [ ] 수정 내용 2 + + + +## 📡 예상 결과 + +## 🔗 참고한 자료 diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 00000000..323248bb --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,9 @@ +## 연관된 이슈 + +이슈링크(url): + + +## ✅ 작업 내용 + + +## 🗣 ️리뷰 요구 사항 \ No newline at end of file diff --git a/src/main/java/org/cotato/csquiz/api/education/controller/EducationController.java b/src/main/java/org/cotato/csquiz/api/education/controller/EducationController.java index edf68c03..83851622 100644 --- a/src/main/java/org/cotato/csquiz/api/education/controller/EducationController.java +++ b/src/main/java/org/cotato/csquiz/api/education/controller/EducationController.java @@ -13,6 +13,7 @@ import org.cotato.csquiz.api.education.dto.WinnerInfoResponse; import org.cotato.csquiz.api.quiz.dto.KingMemberInfo; import org.cotato.csquiz.domain.education.service.EducationService; +import org.cotato.csquiz.domain.education.service.KingMemberService; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; @@ -30,6 +31,7 @@ public class EducationController { private final EducationService educationService; + private final KingMemberService kingMemberService; @GetMapping public ResponseEntity> findEducationListByGeneration( @@ -60,15 +62,29 @@ public ResponseEntity findEducationId(@RequestParam(" return ResponseEntity.ok().body(educationService.findEducationIdOfQuizId(quizId)); } - @GetMapping("/result/kings") + @GetMapping("/kings") public ResponseEntity> findFinalKingMembers(@RequestParam("educationId") Long educationId) { log.info("[{} 교육 결승진출자 조회 컨트롤러]", educationId); - return ResponseEntity.ok().body(educationService.findKingMemberInfo(educationId)); + return ResponseEntity.ok().body(kingMemberService.findKingMemberInfo(educationId)); } - @GetMapping("/result/winner") + @PostMapping("/kings") + public ResponseEntity calculateKingMembers(@RequestParam("educationId") Long educationId) { + log.info("[{} 교육 결승진출자 계산하기]", educationId); + kingMemberService.saveKingMember(educationId); + return ResponseEntity.noContent().build(); + } + + @GetMapping("/winner") public ResponseEntity findWinner(@RequestParam("educationId") Long educationId) { log.info("[{} 교육 우승자 조회 컨트롤러]", educationId); - return ResponseEntity.ok().body(educationService.findWinner(educationId)); + return ResponseEntity.ok().body(kingMemberService.findWinner(educationId)); + } + + @PostMapping("/winner") + public ResponseEntity calculateWinner(@RequestParam("educationId") Long educationId) { + log.info("[{} 교육 우승자 계산]", educationId); + kingMemberService.calculateWinner(educationId); + return ResponseEntity.noContent().build(); } } diff --git a/src/main/java/org/cotato/csquiz/api/socket/controller/SocketController.java b/src/main/java/org/cotato/csquiz/api/socket/controller/SocketController.java index f5a5b7c0..a3f15a05 100644 --- a/src/main/java/org/cotato/csquiz/api/socket/controller/SocketController.java +++ b/src/main/java/org/cotato/csquiz/api/socket/controller/SocketController.java @@ -15,6 +15,7 @@ import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestHeader; import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @RestController @@ -68,4 +69,19 @@ public ResponseEntity stopAllQuiz(@RequestBody @Valid EducationCloseReques public ResponseEntity makeSocketToken(@RequestHeader("Authorization") String authorizationHeader) { return ResponseEntity.ok(socketService.createSocketToken(authorizationHeader)); } + + + @PostMapping("/kings") + public ResponseEntity sendKingCommand(@RequestParam("educationId") Long educationId) { + log.info("[{} 교육 결승진출자 재전송하기]", educationId); + socketService.sendKingCommand(educationId); + return ResponseEntity.noContent().build(); + } + + @PostMapping("/winner") + public ResponseEntity sendWinnerCommand(@RequestParam("educationId") Long educationId) { + log.info("[{} 교육 결승진출자 재전송하기]", educationId); + socketService.sendWinnerCommand(educationId); + return ResponseEntity.noContent().build(); + } } diff --git a/src/main/java/org/cotato/csquiz/api/socket/dto/EducationResultResponse.java b/src/main/java/org/cotato/csquiz/api/socket/dto/EducationResultResponse.java new file mode 100644 index 00000000..21650e14 --- /dev/null +++ b/src/main/java/org/cotato/csquiz/api/socket/dto/EducationResultResponse.java @@ -0,0 +1,13 @@ +package org.cotato.csquiz.api.socket.dto; + +import org.cotato.csquiz.domain.education.entity.Education; + +public record EducationResultResponse( + String command, + Long educationId +) { + public static EducationResultResponse of(String command, Long educationId) { + return new EducationResultResponse(command, educationId); + } + +} diff --git a/src/main/java/org/cotato/csquiz/api/socket/dto/QuizStopResponse.java b/src/main/java/org/cotato/csquiz/api/socket/dto/QuizStopResponse.java index d1d78ac5..c35a477a 100644 --- a/src/main/java/org/cotato/csquiz/api/socket/dto/QuizStopResponse.java +++ b/src/main/java/org/cotato/csquiz/api/socket/dto/QuizStopResponse.java @@ -4,9 +4,11 @@ public record QuizStopResponse( String command, Long quizId ) { - public static QuizStopResponse from(String command, Long quizId) { + public static final String STOP_COMMAND = "stop"; + + public static QuizStopResponse from(Long quizId) { return new QuizStopResponse( - command, + STOP_COMMAND, quizId ); } diff --git a/src/main/java/org/cotato/csquiz/common/error/ErrorCode.java b/src/main/java/org/cotato/csquiz/common/error/ErrorCode.java index cddde6a1..97f12139 100644 --- a/src/main/java/org/cotato/csquiz/common/error/ErrorCode.java +++ b/src/main/java/org/cotato/csquiz/common/error/ErrorCode.java @@ -56,8 +56,12 @@ public enum ErrorCode { SUBJECT_INVALID(HttpStatus.BAD_REQUEST, "E-000", "교육 주제는 NULL이거나 비어있을 수 없습니다."), + KING_MEMBER_EXIST(HttpStatus.CONFLICT, "K-301", "이미 킹킹 멤버가 존재합니다"), + ALREADY_REPLY_CORRECT(HttpStatus.BAD_REQUEST, "R-301", "해당 사용자는 이미 정답 처리되었습니다."), + LAST_QUIZ_SCORER_NOT_EXIST(HttpStatus.CONFLICT, "W-201", "아직 마지막 문제 득점자가 없습니다"), + WINNER_EXIST(HttpStatus.CONFLICT, "W-301", "이미 우승자가 존재합니다"), // 500 오류 -> 서버측에서 처리가 실패한 부분들 WEBSOCKET_SEND_EXCEPTION(HttpStatus.INTERNAL_SERVER_ERROR, "S-001", "소캣 메세지 전송 실패"), IMAGE_PROCESSING_FAIL(HttpStatus.INTERNAL_SERVER_ERROR, "S-002", "이미지 처리에 실패했습니다."), diff --git a/src/main/java/org/cotato/csquiz/common/websocket/WebSocketHandler.java b/src/main/java/org/cotato/csquiz/common/websocket/WebSocketHandler.java index 2b72604d..a0ffa8c2 100644 --- a/src/main/java/org/cotato/csquiz/common/websocket/WebSocketHandler.java +++ b/src/main/java/org/cotato/csquiz/common/websocket/WebSocketHandler.java @@ -2,6 +2,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import org.cotato.csquiz.api.socket.dto.CsQuizStopResponse; +import org.cotato.csquiz.api.socket.dto.EducationResultResponse; import org.cotato.csquiz.api.socket.dto.QuizStartResponse; import org.cotato.csquiz.api.socket.dto.QuizStatusResponse; import org.cotato.csquiz.api.socket.dto.QuizStopResponse; @@ -118,14 +119,23 @@ public void startQuiz(Long quizId) { } public void stopQuiz(Quiz quiz) { - String command = ""; - if (quiz.getNumber() == 9) { - command = KING_COMMAND; + QuizStopResponse response = QuizStopResponse.from(quiz.getId()); + for (WebSocketSession clientSession : CLIENTS.values()) { + sendMessage(clientSession, response); } - if (quiz.getNumber() == 10) { - command = WINNER_COMMAND; + } + + public void sendKingMemberCommand(Long educationId) { + EducationResultResponse response = EducationResultResponse.of(KING_COMMAND, educationId); + + for (WebSocketSession clientSession : CLIENTS.values()) { + sendMessage(clientSession, response); } - QuizStopResponse response = QuizStopResponse.from(command, quiz.getId()); + } + + public void sendWinnerCommand(Long educationId) { + EducationResultResponse response = EducationResultResponse.of(WINNER_COMMAND, educationId); + for (WebSocketSession clientSession : CLIENTS.values()) { sendMessage(clientSession, response); } diff --git a/src/main/java/org/cotato/csquiz/domain/education/repository/KingMemberRepository.java b/src/main/java/org/cotato/csquiz/domain/education/repository/KingMemberRepository.java index 80841862..1162d428 100644 --- a/src/main/java/org/cotato/csquiz/domain/education/repository/KingMemberRepository.java +++ b/src/main/java/org/cotato/csquiz/domain/education/repository/KingMemberRepository.java @@ -7,4 +7,6 @@ public interface KingMemberRepository extends JpaRepository { List findAllByEducation(Education education); + + boolean existsByEducation(Education education); } diff --git a/src/main/java/org/cotato/csquiz/domain/education/repository/QuizRepository.java b/src/main/java/org/cotato/csquiz/domain/education/repository/QuizRepository.java index 078cb08f..dee1e5ed 100644 --- a/src/main/java/org/cotato/csquiz/domain/education/repository/QuizRepository.java +++ b/src/main/java/org/cotato/csquiz/domain/education/repository/QuizRepository.java @@ -1,5 +1,6 @@ package org.cotato.csquiz.domain.education.repository; +import org.cotato.csquiz.domain.education.entity.Education; import org.cotato.csquiz.domain.education.entity.Quiz; import org.cotato.csquiz.domain.education.enums.QuizStatus; import java.util.List; @@ -29,4 +30,8 @@ public interface QuizRepository extends JpaRepository { @Modifying @Query("select q from Quiz q where q.education.id in :educationIds") List findAllByEducationIdsInQuery(@Param("educationIds") List educationIds); + + Optional findByEducationIdAndNumber(Long educationId, Integer i); + + Optional findFirstByEducationOrderByNumberDesc(Education education); } diff --git a/src/main/java/org/cotato/csquiz/domain/education/repository/WinnerRepository.java b/src/main/java/org/cotato/csquiz/domain/education/repository/WinnerRepository.java index 3af17527..c36b5476 100644 --- a/src/main/java/org/cotato/csquiz/domain/education/repository/WinnerRepository.java +++ b/src/main/java/org/cotato/csquiz/domain/education/repository/WinnerRepository.java @@ -7,4 +7,6 @@ public interface WinnerRepository extends JpaRepository { Optional findByEducation(Education education); + + boolean existsByEducation(Education education); } diff --git a/src/main/java/org/cotato/csquiz/domain/education/service/EducationService.java b/src/main/java/org/cotato/csquiz/domain/education/service/EducationService.java index 02572c8e..615d9514 100644 --- a/src/main/java/org/cotato/csquiz/domain/education/service/EducationService.java +++ b/src/main/java/org/cotato/csquiz/domain/education/service/EducationService.java @@ -36,11 +36,8 @@ @Slf4j public class EducationService { - private final MemberService memberService; private final EducationRepository educationRepository; - private final KingMemberRepository kingMemberRepository; private final QuizRepository quizRepository; - private final WinnerRepository winnerRepository; private final SessionRepository sessionRepository; @Transactional @@ -97,32 +94,6 @@ public List findEducationListByGeneration(Long generationI .toList(); } - public List findKingMemberInfo(Long educationId) { - Education findEducation = educationRepository.findById(educationId) - .orElseThrow(() -> new EntityNotFoundException("해당 교육을 찾을 수 없습니다.")); - List kingMembers = kingMemberRepository.findAllByEducation(findEducation); - validateIsEmpty(kingMembers); - return kingMembers.stream() - .map(kingMember -> memberService.findById(kingMember.getMemberId())) - .map(member -> KingMemberInfo.from(member, memberService.findBackFourNumber(member))) - .toList(); - } - - private void validateIsEmpty(List kingMembers) { - if (kingMembers.isEmpty()) { - throw new EntityNotFoundException("아직 결승 진출자가 결정되지 않았습니다."); - } - } - - public WinnerInfoResponse findWinner(Long educationId) { - Education findEducation = educationRepository.findById(educationId) - .orElseThrow(() -> new EntityNotFoundException("해당 교육을 찾을 수 없습니다.")); - Winner findWinner = winnerRepository.findByEducation(findEducation) - .orElseThrow(() -> new EntityNotFoundException("해당 교육의 우승자를 찾을 수 없습니다.")); - Member findMember = memberService.findById(findWinner.getMemberId()); - return WinnerInfoResponse.of(findWinner, findMember, memberService.findBackFourNumber(findMember)); - } - public EducationIdOfQuizResponse findEducationIdOfQuizId(Long quizId) { Quiz quiz = quizRepository.findById(quizId) .orElseThrow(() -> new EntityNotFoundException("해당 문제를 찾을 수 없습니다.")); diff --git a/src/main/java/org/cotato/csquiz/domain/education/service/KingMemberService.java b/src/main/java/org/cotato/csquiz/domain/education/service/KingMemberService.java index 61315924..6f6de88d 100644 --- a/src/main/java/org/cotato/csquiz/domain/education/service/KingMemberService.java +++ b/src/main/java/org/cotato/csquiz/domain/education/service/KingMemberService.java @@ -8,11 +8,16 @@ import java.util.stream.Collectors; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.cotato.csquiz.api.education.dto.WinnerInfoResponse; +import org.cotato.csquiz.api.quiz.dto.KingMemberInfo; +import org.cotato.csquiz.common.error.ErrorCode; +import org.cotato.csquiz.common.error.exception.AppException; import org.cotato.csquiz.domain.education.entity.Education; import org.cotato.csquiz.domain.education.entity.KingMember; import org.cotato.csquiz.domain.education.entity.Quiz; import org.cotato.csquiz.domain.education.entity.Scorer; import org.cotato.csquiz.domain.education.entity.Winner; +import org.cotato.csquiz.domain.education.repository.EducationRepository; import org.cotato.csquiz.domain.education.repository.QuizRepository; import org.cotato.csquiz.domain.education.repository.ScorerRepository; import org.cotato.csquiz.domain.auth.entity.Member; @@ -35,13 +40,20 @@ public class KingMemberService { private final KingMemberRepository kingMemberRepository; private final ScorerRepository scorerRepository; private final WinnerRepository winnerRepository; + private final EducationRepository educationRepository; - public List calculateKingMember(Education education) { - List members = findKingMembersFromEducation(education); + @Transactional + public void saveKingMember(Long educationId) { + Education education = findEducationById(educationId); + + checkKingMemberExist(education); - return members.stream() + List kingMembers = findKingMembersFromEducation(education).stream() .map(member -> KingMember.of(member, education)) .toList(); + + kingMemberRepository.saveAll(kingMembers); + saveWinnerIfKingMemberIsOne(education); } private List findKingMembersFromEducation(Education education) { @@ -64,13 +76,7 @@ private List findKingMembers(List scorers) { .toList(); } - @Transactional - public void saveKingMembers(List kingMembers) { - kingMemberRepository.saveAll(kingMembers); - } - - @Transactional - public void saveWinnerIfKingMemberIsOne(Education education) { + private void saveWinnerIfKingMemberIsOne(Education education) { List kingMembers = kingMemberRepository.findAllByEducation(education); if (kingMembers.size() == 1) { Member findMember = memberRepository.findById(kingMembers.get(0).getMemberId()) @@ -80,13 +86,18 @@ public void saveWinnerIfKingMemberIsOne(Education education) { } @Transactional - public void saveWinnerIfNoWinnerExist(Quiz quiz) { - Education education = quiz.getEducation(); - if (isWinnerExist(education)) { - Scorer findScorer = scorerRepository.findByQuizId(quiz.getId()) - .orElseThrow(() -> new EntityNotFoundException("해당 퀴즈엔 득점자가 존재하지 않습니다.")); - saveWinner(findScorer.getMemberId(), education); + public void calculateWinner(Long educationId) { + Education education = findEducationById(educationId); + if (winnerRepository.existsByEducation(education)) { + throw new AppException(ErrorCode.WINNER_EXIST); } + + Quiz quiz = quizRepository.findFirstByEducationOrderByNumberDesc(education) + .orElseThrow(() -> new EntityNotFoundException("마지막 문제가 없습니다")); + Scorer lastQuizScorer = scorerRepository.findByQuizId(quiz.getId()) + .orElseThrow(() -> new EntityNotFoundException("마지막 퀴즈 득점자가 존재하지 않습니다.")); + + saveWinner(lastQuizScorer.getMemberId(), education); } @Transactional @@ -95,7 +106,40 @@ public void saveWinner(final Long memberId, final Education education) { winnerRepository.save(winner); } - public boolean isWinnerExist(Education education) { - return winnerRepository.findByEducation(education).isPresent(); + public List findKingMemberInfo(Long educationId) { + Education findEducation = educationRepository.findById(educationId) + .orElseThrow(() -> new EntityNotFoundException("해당 교육을 찾을 수 없습니다.")); + List kingMembers = kingMemberRepository.findAllByEducation(findEducation); + validateIsEmpty(kingMembers); + return kingMembers.stream() + .map(kingMember -> memberService.findById(kingMember.getMemberId())) + .map(member -> KingMemberInfo.from(member, memberService.findBackFourNumber(member))) + .toList(); + } + + private void validateIsEmpty(List kingMembers) { + if (kingMembers.isEmpty()) { + throw new EntityNotFoundException("아직 결승 진출자가 결정되지 않았습니다."); + } + } + + public WinnerInfoResponse findWinner(Long educationId) { + Education findEducation = educationRepository.findById(educationId) + .orElseThrow(() -> new EntityNotFoundException("해당 교육을 찾을 수 없습니다.")); + Winner findWinner = winnerRepository.findByEducation(findEducation) + .orElseThrow(() -> new EntityNotFoundException("해당 교육의 우승자를 찾을 수 없습니다.")); + Member findMember = memberService.findById(findWinner.getMemberId()); + return WinnerInfoResponse.of(findWinner, findMember, memberService.findBackFourNumber(findMember)); + } + + private Education findEducationById(Long educationId) { + return educationRepository.findById(educationId) + .orElseThrow(() -> new EntityNotFoundException("해당 교육 id:" + educationId + " 찾다가 에러 발생했습니다.")); + } + + private void checkKingMemberExist(Education education) { + if (kingMemberRepository.existsByEducation(education)) { + throw new AppException(ErrorCode.KING_MEMBER_EXIST); + } } } diff --git a/src/main/java/org/cotato/csquiz/domain/education/service/SocketService.java b/src/main/java/org/cotato/csquiz/domain/education/service/SocketService.java index 4f60e9a4..6e3f8e9b 100644 --- a/src/main/java/org/cotato/csquiz/domain/education/service/SocketService.java +++ b/src/main/java/org/cotato/csquiz/domain/education/service/SocketService.java @@ -19,8 +19,12 @@ import org.cotato.csquiz.common.error.exception.AppException; import org.cotato.csquiz.common.error.ErrorCode; import org.cotato.csquiz.common.websocket.WebSocketHandler; +import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestParam; @Service @RequiredArgsConstructor @@ -31,7 +35,6 @@ public class SocketService { private final WebSocketHandler webSocketHandler; private final QuizRepository quizRepository; private final EducationRepository educationRepository; - private final KingMemberService kingMemberService; private final JwtTokenProvider jwtTokenProvider; @@ -106,16 +109,8 @@ public void stopQuizSolve(QuizSocketRequest request) { checkEducationOpen(quiz.getEducation()); quiz.updateStart(QuizStatus.QUIZ_OFF); - if (quiz.getNumber() == 9) { - List kingMembers = kingMemberService.calculateKingMember(quiz.getEducation()); - kingMemberService.saveKingMembers(kingMembers); - kingMemberService.saveWinnerIfKingMemberIsOne(quiz.getEducation()); - webSocketHandler.stopQuiz(quiz); - } - if (quiz.getNumber() == 10) { - kingMemberService.saveWinnerIfNoWinnerExist(quiz); - webSocketHandler.stopQuiz(quiz); - } + + webSocketHandler.stopQuiz(quiz); } @Transactional @@ -171,4 +166,12 @@ private Education findEducationById(Long educationId) { return educationRepository.findById(educationId) .orElseThrow(() -> new EntityNotFoundException("해당 교육을 찾을 수 없습니다.")); } + + public void sendKingCommand(Long educationId) { + webSocketHandler.sendKingMemberCommand(educationId); + } + + public void sendWinnerCommand(Long educationId) { + webSocketHandler.sendWinnerCommand(educationId); + } }