-
Notifications
You must be signed in to change notification settings - Fork 0
Refactor: 성능 개선, 로직 수정 #15
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
f1c14fc
e4fff74
d2d7199
7e64def
386cec8
8ec98eb
b13a8ef
fd1b3d7
987057e
a597c7c
01c801b
7076c63
d71619f
10a8838
71f9c2c
7f2acd3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,27 +1,23 @@ | ||
| FROM eclipse-temurin:17-jdk AS build | ||
| FROM gradle:8.12-jdk17 AS build | ||
|
|
||
| WORKDIR /app | ||
|
|
||
| ARG GPR_USER | ||
| ARG GPR_TOKEN | ||
|
|
||
| COPY gradlew . | ||
| COPY gradle gradle | ||
| COPY build.gradle . | ||
| COPY settings.gradle . | ||
|
|
||
| RUN chmod +x gradlew | ||
| COPY build.gradle settings.gradle ./ | ||
| COPY gradle ./gradle | ||
|
|
||
| RUN ./gradlew dependencies --no-daemon \ | ||
| -PGPR_USER=${GPR_USER} \ | ||
| -PGPR_TOKEN=${GPR_TOKEN} || true | ||
| RUN GPR_USER=${GPR_USER} GPR_TOKEN=${GPR_TOKEN} gradle dependencies --no-daemon || true | ||
|
|
||
| COPY src src | ||
| COPY src ./src | ||
|
|
||
| RUN ./gradlew bootJar -x test --no-daemon \ | ||
| -PGPR_USER=${GPR_USER} \ | ||
| -PGPR_TOKEN=${GPR_TOKEN} | ||
| RUN GPR_USER=${GPR_USER} GPR_TOKEN=${GPR_TOKEN} gradle bootJar --no-daemon -x test | ||
|
|
||
| FROM eclipse-temurin:17-jre | ||
|
|
||
| WORKDIR /app | ||
|
|
||
| COPY --from=build /app/build/libs/*.jar app.jar | ||
|
|
||
| ENTRYPOINT ["java", "-jar", "app.jar"] | ||
|
LimJinKeon marked this conversation as resolved.
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1 +1 @@ | ||
| CREATE SCHEMA IF NOT EXISTS queue; | ||
| CREATE SCHEMA IF NOT EXISTS queue_service; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,50 @@ | ||
| package org.ticketing.queue.application.service; | ||
|
|
||
| import lombok.RequiredArgsConstructor; | ||
| import lombok.extern.slf4j.Slf4j; | ||
| import org.springframework.stereotype.Service; | ||
| import org.ticketing.queue.domain.exception.UnauthorizedClubAdminException; | ||
| import org.ticketing.queue.infrastructure.feign.ClubFeignClient; | ||
| import org.ticketing.queue.infrastructure.feign.MatchFeignClient; | ||
| import org.ticketing.queue.infrastructure.feign.response.MatchResponse; | ||
|
|
||
| import java.util.UUID; | ||
| import java.util.concurrent.CompletableFuture; | ||
|
|
||
| @Slf4j | ||
| @Service | ||
| @RequiredArgsConstructor | ||
| public class MatchAuthorizationService { | ||
|
|
||
| private final MatchFeignClient matchFeignClient; | ||
| private final ClubFeignClient clubFeignClient; | ||
|
|
||
| private static final String SERVICE_NAME = "queue-service"; | ||
|
|
||
| public void validateClubAdmin(UUID matchId, UUID requestUserId) { | ||
| // 1. 경기 정보 조회 | ||
| MatchResponse match = matchFeignClient.getMatch(matchId, SERVICE_NAME); | ||
|
|
||
| // 2. 홈/어웨이 클럽 관리자 ID 병렬 조회 | ||
| CompletableFuture<UUID> homeFuture = CompletableFuture.supplyAsync(() -> | ||
| clubFeignClient.getClub(match.homeClubId(), SERVICE_NAME).adminId() | ||
| ); | ||
| CompletableFuture<UUID> awayFuture = CompletableFuture.supplyAsync(() -> | ||
| clubFeignClient.getClub(match.awayClubId(), SERVICE_NAME).adminId() | ||
| ); | ||
|
|
||
| UUID homeAdminId = homeFuture.join(); | ||
| UUID awayAdminId = awayFuture.join(); | ||
|
Comment on lines
+29
to
+37
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: find . -type f -name "MatchAuthorizationService.java" | head -20Repository: 3s-ticketing/queue-service Length of output: 157 🏁 Script executed: # Get the file size first to ensure we can read it
wc -l src/main/java/org/ticketing/queue/application/service/MatchAuthorizationService.java 2>/dev/null || find . -type f -name "MatchAuthorizationService.java" -exec wc -l {} \;Repository: 3s-ticketing/queue-service Length of output: 158 🏁 Script executed: # Read the entire file to see the context
cat -n src/main/java/org/ticketing/queue/application/service/MatchAuthorizationService.java 2>/dev/null || find . -type f -name "MatchAuthorizationService.java" -exec cat -n {} \;Repository: 3s-ticketing/queue-service Length of output: 2317 🏁 Script executed: # Search for global exception handlers
find . -type f -name "*ExceptionHandler*.java" -o -name "*ControllerAdvice*.java" | head -20Repository: 3s-ticketing/queue-service Length of output: 52 🏁 Script executed: # Search for exception handlers in the codebase
rg -t java "ControllerAdvice|ExceptionHandler|RestControllerAdvice" -A 3 | head -100Repository: 3s-ticketing/queue-service Length of output: 52 🏁 Script executed: # Search for executor beans
rg -t java "Executor|ThreadPoolTaskExecutor|ExecutorService" | grep -i bean | head -20Repository: 3s-ticketing/queue-service Length of output: 52 🏁 Script executed: # Search for CompletionException handling
rg -t java "CompletionException" | head -20Repository: 3s-ticketing/queue-service Length of output: 52 🏁 Script executed: # Search for exception handling in main directory structure
find . -type f \( -name "*.java" -o -name "*.xml" -o -name "*.yml" -o -name "*.yaml" \) | grep -E "(config|exception|handler)" | head -20Repository: 3s-ticketing/queue-service Length of output: 1270 🏁 Script executed: # Check for Spring configuration classes
rg -t java "@Configuration|@Bean" | grep -i "exception|error|handler" | head -20Repository: 3s-ticketing/queue-service Length of output: 52 🏁 Script executed: # Look for where validateClubAdmin is called
rg "validateClubAdmin" -B 2 -A 2Repository: 3s-ticketing/queue-service Length of output: 1374 🏁 Script executed: # Check project structure for any config files
ls -la src/main/resources/ 2>/dev/null || find . -path "*/main/resources/*" -type f | head -20Repository: 3s-ticketing/queue-service Length of output: 380 🏁 Script executed: # Read the QueueController to see the context where validateClubAdmin is called
cat -n src/main/java/org/ticketing/queue/presentation/controller/QueueController.java | head -100Repository: 3s-ticketing/queue-service Length of output: 4263 🏁 Script executed: # Check for exception handling in the controller class
rg -t java "QueueController" -A 50 | grep -A 50 "validateClubAdmin" | head -40Repository: 3s-ticketing/queue-service Length of output: 52 🏁 Script executed: # Check application.yml for error handling
cat src/main/resources/application.ymlRepository: 3s-ticketing/queue-service Length of output: 1013 🏁 Script executed: # Check for Feign client and exception handling
cat -n src/main/java/org/ticketing/queue/infrastructure/feign/ClubFeignClient.javaRepository: 3s-ticketing/queue-service Length of output: 882 🏁 Script executed: # Look for any exception handler configuration in infrastructure
find . -type f -name "*.java" -path "*/infrastructure/*" | xargs grep -l "ExceptionHandler\|GlobalExceptionHandler" | head -10Repository: 3s-ticketing/queue-service Length of output: 52 🏁 Script executed: # Search for Feign exception handling
rg -t java "FeignException|feign" -A 3 | head -50Repository: 3s-ticketing/queue-service Length of output: 5010 🏁 Script executed: # Check the ClubFeignClientFallback implementation
cat -n src/main/java/org/ticketing/queue/infrastructure/feign/ClubFeignClientFallback.javaRepository: 3s-ticketing/queue-service Length of output: 849 🏁 Script executed: # Check the MatchFeignClientFallback implementation
cat -n src/main/java/org/ticketing/queue/infrastructure/feign/MatchFeignClientFallback.javaRepository: 3s-ticketing/queue-service Length of output: 858 🏁 Script executed: # Look for `@ExceptionHandler` anywhere in the codebase
rg -t java "@ExceptionHandler" -B 3 -A 5Repository: 3s-ticketing/queue-service Length of output: 52 🏁 Script executed: # Check if NotFoundClubMatchException is a RuntimeException
cat -n src/main/java/org/ticketing/queue/domain/exception/NotFoundClubMatchException.javaRepository: 3s-ticketing/queue-service Length of output: 584 🏁 Script executed: # Search for authorizationExecutor or any executor bean that might handle this
rg -t java "authorizationExecutor"Repository: 3s-ticketing/queue-service Length of output: 52 🏁 Script executed: # Search for any TaskExecutor or ExecutorService beans
rg -t java "@Bean.*[Ee]xecutor|@Bean.*[Ee]xecutor" -A 2Repository: 3s-ticketing/queue-service Length of output: 52 Use dedicated executor and unwrap exceptions from The current code uses Configure a dedicated executor and unwrap completion exceptions to preserve proper error handling: Suggested approach- CompletableFuture<UUID> homeFuture = CompletableFuture.supplyAsync(() ->
+ CompletableFuture<UUID> homeFuture = CompletableFuture.supplyAsync(() ->
clubFeignClient.getClub(match.homeClubId(), SERVICE_NAME).adminId()
- );
+ , authorizationExecutor);
- CompletableFuture<UUID> awayFuture = CompletableFuture.supplyAsync(() ->
+ CompletableFuture<UUID> awayFuture = CompletableFuture.supplyAsync(() ->
clubFeignClient.getClub(match.awayClubId(), SERVICE_NAME).adminId()
- );
+ , authorizationExecutor);
- UUID homeAdminId = homeFuture.join();
- UUID awayAdminId = awayFuture.join();
+ UUID homeAdminId;
+ UUID awayAdminId;
+ try {
+ homeAdminId = homeFuture.join();
+ awayAdminId = awayFuture.join();
+ } catch (CompletionException e) {
+ throw (e.getCause() instanceof RuntimeException re) ? re : e;
+ }🤖 Prompt for AI Agents |
||
|
|
||
| // 3. 권한 검증 | ||
| boolean isAuthorized = requestUserId.equals(homeAdminId) | ||
| || requestUserId.equals(awayAdminId); | ||
|
|
||
| if (!isAuthorized) { | ||
| log.warn("[Auth] CLUB_ADMIN 권한 없음. matchId={}, requestUserId={}", matchId, requestUserId); | ||
| throw new UnauthorizedClubAdminException(matchId, requestUserId); | ||
| } | ||
|
|
||
| log.info("[Auth] CLUB_ADMIN 검증 완료. matchId={}, requestUserId={}", matchId, requestUserId); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| package org.ticketing.queue.domain.exception; | ||
|
|
||
| import org.springframework.http.HttpStatus; | ||
| import org.ticketing.common.exception.CustomException; | ||
|
|
||
| import java.util.UUID; | ||
|
|
||
| public class NotFoundClubMatchException extends CustomException { | ||
|
|
||
| public NotFoundClubMatchException(UUID matchId, UUID clubId) { | ||
| super(String.format("해당 경기/클럽 조회 실패. matchId=%s, clubId=%s", matchId, clubId), HttpStatus.NOT_FOUND); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| package org.ticketing.queue.domain.exception; | ||
|
|
||
| import org.springframework.http.HttpStatus; | ||
| import org.ticketing.common.exception.CustomException; | ||
|
|
||
| import java.util.UUID; | ||
|
|
||
| public class UnauthorizedClubAdminException extends CustomException { | ||
|
|
||
| public UnauthorizedClubAdminException(UUID matchId, UUID userId) { | ||
| super(String.format("해당 경기의 클럽 관리자가 아닙니다. matchId=%s, userId=%s", matchId, userId), HttpStatus.UNAUTHORIZED); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,9 +1,10 @@ | ||
| package org.ticketing.queue.domain.model; | ||
|
|
||
| public enum AcquireResult { | ||
| SUCCESS, // 1: 슬롯+토큰 선점 성공 | ||
| NO_SLOT, // -1: 슬롯 없음 | ||
| NOT_INITIALIZED, // -2: 슬롯 미초기화 | ||
| PENDING, // -3: 다른 스레드 발급 중 | ||
| ALREADY_ISSUED // -4: 이미 발급 완료 | ||
| SUCCESS, // 1: 슬롯+토큰 선점 성공 | ||
| NO_SLOT, // -1: 슬롯 없음 | ||
| NOT_INITIALIZED, // -2: 슬롯 미초기화 | ||
| PENDING, // -3: 다른 스레드 발급 중 | ||
| ALREADY_ISSUED, // -4: 이미 발급 완료 | ||
| USER_NOT_IN_QUEUE // -5: 유저가 이미 대기열에서 제거됨 (ban/refresh/rollback 등) | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| package org.ticketing.queue.domain.model; | ||
|
|
||
| import java.time.LocalDateTime; | ||
|
|
||
| public record SlotAcquire(AcquireResult status, LocalDateTime enteredAt) { | ||
|
|
||
| public static SlotAcquire of(AcquireResult status) { | ||
| return new SlotAcquire(status, null); | ||
| } | ||
|
|
||
| public static SlotAcquire success(LocalDateTime enteredAt) { | ||
| return new SlotAcquire(AcquireResult.SUCCESS, enteredAt); | ||
| } | ||
| } |
Uh oh!
There was an error while loading. Please reload this page.