From f3b8dd43e1b6c9b12bc63fc1781cfe042b6f0d92 Mon Sep 17 00:00:00 2001 From: lunaticbum Date: Tue, 11 Nov 2025 17:45:17 +0900 Subject: [PATCH] ... --- .../back/lun/controllers/PuzzleController.kt | 21 +++++++++--------- .../lunaticbum/back/lun/model/PuzzleData.kt | 22 +++++++++++++------ 2 files changed, 26 insertions(+), 17 deletions(-) diff --git a/src/main/kotlin/kr/lunaticbum/back/lun/controllers/PuzzleController.kt b/src/main/kotlin/kr/lunaticbum/back/lun/controllers/PuzzleController.kt index 167002b..98d57a0 100644 --- a/src/main/kotlin/kr/lunaticbum/back/lun/controllers/PuzzleController.kt +++ b/src/main/kotlin/kr/lunaticbum/back/lun/controllers/PuzzleController.kt @@ -269,17 +269,18 @@ class GameRankController(private val gameRankService: GameRankService) { /** * [수정] 모든 게임을 위한 통합 랭킹 등록 엔드포인트 (에러 처리 추가) */ - @PostMapping("/submit") - fun submitUnifiedRank(@RequestBody rankDto: UnifiedRankDto): Mono> { - return gameRankService.submitRank(rankDto) - .map { savedRank -> ResponseEntity.ok(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> { + + return gameRankService.submitRank(rankDto) // 1. 반환 타입: Flux + .collectList() // 2. [핵심] Flux를 Mono>로 변환 + .map { rankList -> // 3. Mono를 map + // 4. 리스트(rankList)를 body에 담아 OK(200) 응답 + ResponseEntity.ok(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 ?: "랭킹 등록 중 오류 발생")) } } diff --git a/src/main/kotlin/kr/lunaticbum/back/lun/model/PuzzleData.kt b/src/main/kotlin/kr/lunaticbum/back/lun/model/PuzzleData.kt index 8b1d2f1..ab67277 100644 --- a/src/main/kotlin/kr/lunaticbum/back/lun/model/PuzzleData.kt +++ b/src/main/kotlin/kr/lunaticbum/back/lun/model/PuzzleData.kt @@ -685,7 +685,7 @@ interface GameRankRepository : ReactiveSortingRepository { contextId: String? ): Flux - // [신규 추가] 특정 플레이어의 랭킹을 최신순으로 조회 + // [신규 추가] 특정 플레이어의 G킹을 최신순으로 조회 fun findByPlayerNameOrderByTimestampDesc(playerName: String): Flux // 🔽 [추가] @@ -718,12 +718,14 @@ class GameRankService( /** * [수정] 공통 DTO를 받아 랭킹을 저장 (Blocking IO 및 모든 예외 처리) + * 🔽 [수정] 반환 타입을 Mono -> Flux로 변경 */ - fun submitRank(rankDto: UnifiedRankDto): Mono { + fun submitRank(rankDto: UnifiedRankDto): Flux { val auth = SecurityContextHolder.getContext().authentication val isAuthenticated = auth != null && auth.isAuthenticated && auth !is AnonymousAuthenticationToken - if (isAuthenticated) { + // 1. 랭크 저장 로직을 'saveOperation' Mono로 분리 (반환 타입은 아직 Mono) + val saveOperation: Mono = 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)을 반환 + return saveOperation.thenMany( + getRanks(rankDto.gameType, rankDto.contextId) + ) } + /** * 특정 플레이어의 모든 게임 랭킹을 조회합니다. (변경 없음) */