This commit is contained in:
lunaticbum 2025-11-11 17:45:17 +09:00
parent 93ff0354dc
commit f3b8dd43e1
2 changed files with 26 additions and 17 deletions

View File

@ -269,17 +269,18 @@ class GameRankController(private val gameRankService: GameRankService) {
/**
* [수정] 모든 게임을 위한 통합 랭킹 등록 엔드포인트 (에러 처리 추가)
*/
@PostMapping("/submit")
fun submitUnifiedRank(@RequestBody rankDto: UnifiedRankDto): Mono<ResponseEntity<Any>> {
return gameRankService.submitRank(rankDto)
.map { savedRank -> ResponseEntity.ok<Any>(savedRank) }
.onErrorResume(IllegalArgumentException::class.java) { e ->
// 서비스에서 이름 중복 예외가 발생하면 409 Conflict 상태와 에러 메시지를 반환
Mono.just(ResponseEntity.status(HttpStatus.CONFLICT).body(e.message))
@PostMapping("/api/ranks/submit") // 👈 실제 엔드포인트 경로에 맞게 수정하세요.
fun submitRank(@RequestBody rankDto: UnifiedRankDto): Mono<ResponseEntity<Any>> {
return gameRankService.submitRank(rankDto) // 1. 반환 타입: Flux<GameRank>
.collectList() // 2. [핵심] Flux를 Mono<List<GameRank>>로 변환
.map { rankList -> // 3. Mono<List>를 map
// 4. 리스트(rankList)를 body에 담아 OK(200) 응답
ResponseEntity.ok<Any>(rankList)
}
.onErrorResume {
// 기타 예외는 500 Internal Server Error로 처리
Mono.just(ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(it.message))
.onErrorResume { e -> // 👈 [중요] 이름 중복 등 서비스 레벨의 예외 처리
// 5. GameRankService에서 발생한 예외(e) 메시지를 400 Bad Request로 반환
Mono.just(ResponseEntity.badRequest().body(e.message ?: "랭킹 등록 중 오류 발생"))
}
}

View File

@ -685,7 +685,7 @@ interface GameRankRepository : ReactiveSortingRepository<GameRank, String> {
contextId: String?
): Flux<GameRank>
// [신규 추가] 특정 플레이어의 킹을 최신순으로 조회
// [신규 추가] 특정 플레이어의 G킹을 최신순으로 조회
fun findByPlayerNameOrderByTimestampDesc(playerName: String): Flux<GameRank>
// 🔽 [추가]
@ -718,12 +718,14 @@ class GameRankService(
/**
* [수정] 공통 DTO를 받아 랭킹을 저장 (Blocking IO 모든 예외 처리)
* 🔽 [수정] 반환 타입을 Mono<GameRank> -> Flux<GameRank> 변경
*/
fun submitRank(rankDto: UnifiedRankDto): Mono<GameRank> {
fun submitRank(rankDto: UnifiedRankDto): Flux<GameRank> {
val auth = SecurityContextHolder.getContext().authentication
val isAuthenticated = auth != null && auth.isAuthenticated && auth !is AnonymousAuthenticationToken
if (isAuthenticated) {
// 1. 랭크 저장 로직을 'saveOperation' Mono로 분리 (반환 타입은 아직 Mono<GameRank>)
val saveOperation: Mono<GameRank> = if (isAuthenticated) {
// --- 1. 인증된 사용자 (로그인 상태) ---
val principal = auth.principal as UserDetails
val authenticatedUserId = principal.username
@ -736,7 +738,7 @@ class GameRankService(
secondaryScore = rankDto.secondaryScore
)
// 로그인 유저는 중복 검사 없이 바로 저장
return rankRepository.save(gameRank)
rankRepository.save(gameRank)
} else {
// --- 2. 익명 사용자 (비로그인 상태) ---
@ -790,12 +792,18 @@ class GameRankService(
secondaryScore = rankDto.secondaryScore
)))
// 4. 랭킹 저장
// [수정] 'findFirstByUserId'는 이제 필요 없으므로 'flatMap' 대신 'then' 사용
return gameRankMono.flatMap { rankRepository.save(it) }
// 4. 랭킹 저장 (saveOperation에 할당)
gameRankMono.flatMap { rankRepository.save(it) }
}
// 2. 🔽 랭크 저장이 성공한 '후에' (.thenMany)
// 3. 🔽 'getRanks'를 호출하여 업데이트된 랭킹 목록(Flux<GameRank>)을 반환
return saveOperation.thenMany(
getRanks(rankDto.gameType, rankDto.contextId)
)
}
/**
* 특정 플레이어의 모든 게임 랭킹을 조회합니다. (변경 없음)
*/