Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@


public record AIErrorRes(
String error
String detail
) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,147 +27,122 @@ public class AIClientService {
@Value("${ai-server.url}")
private String AI_SERVER_BASE_URL;

public String getGameStartMessage(String roomId, AIGameStartReq request){
try {
return webClient.post()
.uri(AI_SERVER_BASE_URL + "myomyo/" + roomId + "/start")
.bodyValue(request)
.retrieve()
.onStatus(httpStatusCode -> httpStatusCode.is4xxClientError() || httpStatusCode.is5xxServerError()
, clientResponse -> clientResponse.bodyToMono(AIErrorRes.class).flatMap(error -> Mono.error(
new SocketCustomException(GAME_ERROR, GameExceptionCode.AI_SERVER_ERROR))))
.bodyToMono(String.class)
.timeout(Duration.ofSeconds(60))
.block();
} catch (Exception e){
log.error("[AI Server Exception] error on GAME_START: {}", e.getClass().getName());
throw new SocketCustomException(GAME_ERROR, GameExceptionCode.AI_SERVER_ERROR);
}
/**
* AI 서버로 POST 요청을 보내는 제네릭 메서드.
* 비동기 호출을 처리하며, 응답을 Mono<R> 형태로 반환합니다.
* @param path AI 서버의 API 경로
* @param requestBody 요청 본문
* @param responseClass 응답 본문을 매핑할 클래스 타입
* @param errorContext 로깅 및 예외 처리를 위한 컨텍스트 문자열
* @param <T> 요청 본문의 타입
* @param <R> 응답 본문의 타입
* @return AI 서버로부터의 응답을 담은 Mono 객체
*/
private <T, R> Mono<R> postToAiServer(String path, T requestBody, Class<R> responseClass, String errorContext) {
// todo: 비동기? 동기? 비동기? 동기? 비동기? 동기?
// todo: 모노? 안모노? 모노? 안모노? 모노? 안모노?
return webClient.post()
.uri(AI_SERVER_BASE_URL + path)
.bodyValue(requestBody)
.retrieve()
.onStatus(httpStatusCode -> httpStatusCode.is4xxClientError() || httpStatusCode.is5xxServerError(),
clientResponse -> clientResponse.bodyToMono(AIErrorRes.class).flatMap(error -> {
log.error("AI Server Error on Path: \"{}\", StatusCode: {}, Content: {}", path, clientResponse.statusCode(), error.detail());
return Mono.error(
new SocketCustomException(GAME_ERROR, GameExceptionCode.AI_SERVER_ERROR));
}))
.bodyToMono(responseClass)
.timeout(Duration.ofSeconds(60))
.doOnError(e -> log.error("[AI Server Exception] error on {}: {}", errorContext, e.getClass().getName()))
.onErrorMap(e -> {
if (e instanceof SocketCustomException) {
return e;
}
return new SocketCustomException(GAME_ERROR, GameExceptionCode.AI_SERVER_ERROR);
});
}

public String getRoundStartMessage(String roomId, AIRoundStartReq request){
try {
return webClient.post()
.uri(AI_SERVER_BASE_URL + "myomyo/" + roomId + "/round/start")
.bodyValue(request)
.retrieve()
.onStatus(httpStatusCode -> httpStatusCode.is4xxClientError() || httpStatusCode.is5xxServerError()
, clientResponse -> clientResponse.bodyToMono(AIErrorRes.class).flatMap(error -> Mono.error(
new SocketCustomException(GAME_ERROR, GameExceptionCode.AI_SERVER_ERROR))))
.bodyToMono(String.class)
.timeout(Duration.ofSeconds(60))
.block();
}catch (Exception e){
log.error("[AI Server Exception] error on ROUND_START: {}", e.getClass().getName());
throw new SocketCustomException(GAME_ERROR, GameExceptionCode.AI_SERVER_ERROR);
}
/**
* 게임 시작 메시지를 AI 서버에 요청합니다.
* @param roomId 게임방 ID
* @param request 게임 시작 요청 DTO
* @return AI 서버로부터의 응답 메시지를 담은 Mono<String> 객체
*/
public String getGameStartMessage(String roomId, AIGameStartReq request) {
// todo: 비동기? 동기? 비동기? 동기? 비동기? 동기?
// todo: 모노? 안모노? 모노? 안모노? 모노? 안모노?
return postToAiServer("myomyo/" + roomId + "/start", request, String.class, "GAME_START").block();
}

public String getGuessStartMessage(String roomId, AIGuessStartReq request){
try {
return webClient.post()
.uri(AI_SERVER_BASE_URL + "myomyo/" + roomId + "/guess/start")
.bodyValue(request)
.retrieve()
.onStatus(httpStatusCode -> httpStatusCode.is4xxClientError() || httpStatusCode.is5xxServerError(),
clientResponse -> clientResponse.bodyToMono(AIErrorRes.class).flatMap(error -> Mono.error(
new SocketCustomException(GAME_ERROR, GameExceptionCode.AI_SERVER_ERROR))))
.bodyToMono(String.class)
.timeout(Duration.ofSeconds(60))
.block();
} catch (Exception e){
log.error("[AI Server Exception] error on GUESS_START: {}", e.getClass().getName());
throw new SocketCustomException(GAME_ERROR, GameExceptionCode.AI_SERVER_ERROR);
}

/**
* 라운드 시작 메시지를 AI 서버에 요청합니다.
* @param roomId 게임방 ID
* @param request 라운드 시작 요청 DTO
* @return AI 서버로부터의 응답 메시지를 담은 Mono<String> 객체
*/
public String getRoundStartMessage(String roomId, AIRoundStartReq request) {
return postToAiServer("myomyo/" + roomId + "/round/start", request, String.class, "ROUND_START").block();
}

/**
* 추측 시작 메시지를 AI 서버에 요청합니다.
* @param roomId 게임방 ID
* @param request 추측 시작 요청 DTO
* @return AI 서버로부터의 응답 메시지를 담은 Mono<String> 객체
*/
public String getGuessStartMessage(String roomId, AIGuessStartReq request) {
return postToAiServer("myomyo/" + roomId + "/guess/start", request, String.class, "GUESS_START").block();
}

public AIGuessImageRes getGuessImage(AIGuessImageReq request){
try {
return webClient.post()
.uri(AI_SERVER_BASE_URL + "classify")
.bodyValue(request)
.retrieve()
.onStatus(httpStatusCode -> httpStatusCode.is4xxClientError() || httpStatusCode.is5xxServerError()
, clientResponse -> clientResponse.bodyToMono(AIErrorRes.class).flatMap(error -> Mono.error(
new SocketCustomException(GAME_ERROR, GameExceptionCode.AI_SERVER_ERROR))))
.bodyToMono(AIGuessImageRes.class)
.block();
} catch (Exception e) {
log.error("[AI Server Exception] error on GUESS IMAGE: {}", e.getClass().getName());
throw new SocketCustomException(GAME_ERROR, GameExceptionCode.AI_SERVER_ERROR);
}
/**
* 이미지 추측 결과를 AI 서버에 요청합니다.
* @param request 이미지 추측 요청 DTO
* @return AI 서버로부터의 이미지 추측 결과를 담은 Mono<AIGuessImageRes> 객체
*/
public AIGuessImageRes getGuessImage(AIGuessImageReq request) {
return postToAiServer("classify", request, AIGuessImageRes.class, "GUESS_IMAGE").block();
}

public String getGuessMessage(String roomId, AIGuessMessageReq request){
try {
return webClient.post()
.uri(AI_SERVER_BASE_URL + "myomyo/" + roomId + "/guess")
.bodyValue(request)
.retrieve()
.onStatus(httpStatusCode -> httpStatusCode.is4xxClientError() || httpStatusCode.is5xxServerError()
, clientResponse -> clientResponse.bodyToMono(AIErrorRes.class).flatMap(error -> Mono.error(
new SocketCustomException(GAME_ERROR, GameExceptionCode.AI_SERVER_ERROR))))
.bodyToMono(String.class)
.timeout(Duration.ofSeconds(60))
.block();
} catch (Exception e) {
log.error("[AI Server Exception] error on GUESS MESSAGE: {}", e.getClass().getName());
throw new SocketCustomException(GAME_ERROR, GameExceptionCode.AI_SERVER_ERROR);
}


/**
* 추측 메시지를 AI 서버에 요청합니다.
* @param roomId 게임방 ID
* @param request 추측 메시지 요청 DTO
* @return AI 서버로부터의 응답 메시지를 담은 Mono<String> 객체
*/
public String getGuessMessage(String roomId, AIGuessMessageReq request) {
return postToAiServer("myomyo/" + roomId + "/guess", request, String.class, "GUESS_MESSAGE").block();
}

public String getGuessReactMessage(String roomId, AIGuessReactReq request){
try {
return webClient.post()
.uri(AI_SERVER_BASE_URL + "myomyo/" + roomId + "/guess/react")
.bodyValue(request)
.retrieve()
.onStatus(httpStatusCode -> httpStatusCode.is4xxClientError() || httpStatusCode.is5xxServerError()
, clientResponse -> clientResponse.bodyToMono(AIErrorRes.class).flatMap(error -> Mono.error(
new SocketCustomException(GAME_ERROR, GameExceptionCode.AI_SERVER_ERROR))))
.bodyToMono(String.class)
.timeout(Duration.ofSeconds(60))
.block();
} catch (Exception e) {
log.error("[AI Server Exception] error on GUESS REACT: {}", e.getClass().getName());
throw new SocketCustomException(GAME_ERROR, GameExceptionCode.AI_SERVER_ERROR);
}
/**
* 추측 반응 메시지를 AI 서버에 요청합니다.
* @param roomId 게임방 ID
* @param request 추측 반응 요청 DTO
* @return AI 서버로부터의 응답 메시지를 담은 Mono<String> 객체
*/
public String getGuessReactMessage(String roomId, AIGuessReactReq request) {
return postToAiServer("myomyo/" + roomId + "/guess/react", request, String.class, "GUESS_REACT").block();
}

public String getRoundEndMessage(String roomId, AIRoundEndReq request){
try {
return webClient.post()
.uri(AI_SERVER_BASE_URL + "myomyo/" + roomId + "/round/end")
.bodyValue(request)
.retrieve()
.onStatus(httpStatusCode -> httpStatusCode.is4xxClientError() || httpStatusCode.is5xxServerError()
, clientResponse -> clientResponse.bodyToMono(AIErrorRes.class).flatMap(error -> Mono.error(
new SocketCustomException(GAME_ERROR, GameExceptionCode.AI_SERVER_ERROR))))
.bodyToMono(String.class)
.timeout(Duration.ofSeconds(60))
.block();
} catch (Exception e) {
log.error("[AI Server Exception] error on ROUND END: {}", e.getClass().getName());
throw new SocketCustomException(GAME_ERROR, GameExceptionCode.AI_SERVER_ERROR);
}
/**
* 라운드 종료 메시지를 AI 서버에 요청합니다.
* @param roomId 게임방 ID
* @param request 라운드 종료 요청 DTO
* @return AI 서버로부터의 응답 메시지를 담은 Mono<String> 객체
*/
public Mono<String> getRoundEndMessage(String roomId, AIRoundEndReq request) {
return postToAiServer("myomyo/" + roomId + "/round/end", request, String.class, "ROUND_END");
}

/**
* 게임 종료 메시지를 AI 서버에 요청합니다.
* @param roomId 게임방 ID
* @param request 게임 종료 요청 DTO
* @return AI 서버로부터의 응답 메시지를 담은 Mono<String> 객체
*/
public String getGameEndMessage(String roomId, AIGameEndReq request) {
try {
return webClient.post()
.uri(AI_SERVER_BASE_URL + "myomyo/" + roomId + "/end")
.bodyValue(request)
.retrieve()
.onStatus(httpStatusCode -> httpStatusCode.is4xxClientError() || httpStatusCode.is5xxServerError()
, clientResponse -> clientResponse.bodyToMono(AIErrorRes.class).flatMap(error -> Mono.error(
new SocketCustomException(GAME_ERROR, GameExceptionCode.AI_SERVER_ERROR))))
.bodyToMono(String.class)
.timeout(Duration.ofSeconds(60))
.block();
} catch (Exception e) {
log.error("[AI Server Exception] error on GAME END: {}", e.getClass().getName());
throw new SocketCustomException(GAME_ERROR, GameExceptionCode.AI_SERVER_ERROR);
}

return postToAiServer("myomyo/" + roomId + "/end", request, String.class, "GAME_END").block();
}
}
Loading