Skip to content

Commit

Permalink
Merge pull request #47 from MARU-EGG/refactor/exception-추가
Browse files Browse the repository at this point in the history
[refactor] webClient exception 추가로 예외처리
  • Loading branch information
Hoya324 authored Jul 22, 2024
2 parents c7d99e0 + 3da13e4 commit 8b42c4e
Show file tree
Hide file tree
Showing 9 changed files with 102 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import static mju.iphak.maru_egg.common.exception.ErrorCode.*;

import org.springframework.http.HttpStatusCode;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
Expand All @@ -16,6 +17,9 @@
import mju.iphak.maru_egg.answer.dto.request.LLMAskQuestionRequest;
import mju.iphak.maru_egg.answer.dto.response.LLMAnswerResponse;
import mju.iphak.maru_egg.answer.repository.AnswerRepository;
import mju.iphak.maru_egg.common.exception.custom.webClient.BadRequestWebClientException;
import mju.iphak.maru_egg.common.exception.custom.webClient.InternalServerErrorWebClientException;
import mju.iphak.maru_egg.common.exception.custom.webClient.NotFoundWebClientException;
import reactor.core.publisher.Mono;

@RequiredArgsConstructor
Expand Down Expand Up @@ -44,6 +48,22 @@ public Mono<LLMAnswerResponse> askQuestion(LLMAskQuestionRequest request) {
.contentType(MediaType.APPLICATION_FORM_URLENCODED)
.body(BodyInserters.fromFormData(formData))
.retrieve()
.onStatus(
HttpStatusCode::isError,
response -> {
return switch (response.statusCode().value()) {
case 400 -> Mono.error(
new BadRequestWebClientException(
String.format(BAD_REQUEST_WEBCLIENT.getMessage(), "LLM 서버", request.questionType(),
request.questionCategory(), request.question())));
case 404 -> Mono.error(
new NotFoundWebClientException(String.format(NOT_FOUND_WEBCLIENT.getMessage(), "LLM 서버")));
default -> Mono.error(
new InternalServerErrorWebClientException(
String.format(INTERNAL_ERROR_WEBCLIENT.getMessage(), "LLM 서버")));
};
}
)
.bodyToMono(LLMAnswerResponse.class);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
public enum ErrorCode {

// 400 error
BAD_REQUEST_WEBCLIENT(BAD_REQUEST, "%s에 잘못된 요청을 보냈습니다. (questionType: %s, questionCategory: %s, question: %s"),

// 401 error
UNAUTHORIZED_REQUEST(UNAUTHORIZED, "로그인 후 다시 시도해주세요."),
Expand All @@ -24,9 +25,11 @@ public enum ErrorCode {
NOT_FOUND_ANSWER(NOT_FOUND, "답변 id가 %s인 답변을 찾을 수 없습니다."),
NOT_FOUND_ANSWER_BY_QUESTION_ID(NOT_FOUND, "질문 id가 %s인 답변을 찾을 수 없습니다."),
NOT_FOUND_USER(NOT_FOUND, "유저 이메일이 %s인 유저를 찾을 수 없습니다."),
NOT_FOUND_WEBCLIENT(NOT_FOUND, "%s에서 값을 불러오지 못 했습니다."),

// 500 error
INTERNAL_ERROR_SIMILARITY(NOT_FOUND, "contentToken: %s, question: %s인 질문의 유사도를 검사하는 도중 오류가 발생했습니다.");
INTERNAL_ERROR_SIMILARITY(INTERNAL_SERVER_ERROR, "contentToken: %s, question: %s인 질문의 유사도를 검사하는 도중 오류가 발생했습니다."),
INTERNAL_ERROR_WEBCLIENT(INTERNAL_SERVER_ERROR, "%s에서 서버 오류가 발생했습니다.");

private final HttpStatus status;
private final String message;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@

import jakarta.persistence.EntityNotFoundException;
import lombok.extern.slf4j.Slf4j;
import mju.iphak.maru_egg.common.exception.custom.webClient.BadRequestWebClientException;
import mju.iphak.maru_egg.common.exception.custom.webClient.InternalServerErrorWebClientException;
import mju.iphak.maru_egg.common.exception.custom.webClient.NotFoundWebClientException;

@Slf4j
@RestControllerAdvice
Expand Down Expand Up @@ -63,6 +66,31 @@ protected ResponseEntity<ErrorResponse> handleUsernameNotFoundException(Username
.body(ErrorResponse.of(e.getClass().getSimpleName(), NOT_FOUND.value(), e.getMessage()));
}

@ExceptionHandler(BadRequestWebClientException.class)
protected ResponseEntity<ErrorResponse> handleBadRequestWebClientException(BadRequestWebClientException e) {
String timestamp = getCurrentTimestamp();
log.error(LOG_FORMAT, timestamp, e.getClass().getSimpleName(), e.getMessage());
return ResponseEntity.status(BAD_REQUEST)
.body(ErrorResponse.of(e.getClass().getSimpleName(), BAD_REQUEST.value(), e.getMessage()));
}

@ExceptionHandler(NotFoundWebClientException.class)
protected ResponseEntity<ErrorResponse> handleNotFoundWebClientException(NotFoundWebClientException e) {
String timestamp = getCurrentTimestamp();
log.error(LOG_FORMAT, timestamp, e.getClass().getSimpleName(), e.getMessage());
return ResponseEntity.status(NOT_FOUND)
.body(ErrorResponse.of(e.getClass().getSimpleName(), NOT_FOUND.value(), e.getMessage()));
}

@ExceptionHandler(InternalServerErrorWebClientException.class)
protected ResponseEntity<ErrorResponse> handleInternalServerErrorWebClientException(
InternalServerErrorWebClientException e) {
String timestamp = getCurrentTimestamp();
log.error(LOG_FORMAT, timestamp, e.getClass().getSimpleName(), e.getMessage());
return ResponseEntity.status(INTERNAL_SERVER_ERROR)
.body(ErrorResponse.of(e.getClass().getSimpleName(), INTERNAL_SERVER_ERROR.value(), e.getMessage()));
}

private String getCurrentTimestamp() {
return LocalDateTime.now().format(DATE_TIME_FORMATTER);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package mju.iphak.maru_egg.common.exception.custom.webClient;

import org.springframework.web.reactive.function.client.WebClientException;

public class BadRequestWebClientException extends WebClientException {
public BadRequestWebClientException(final String msg) {
super(msg);
}

public BadRequestWebClientException(final String msg, final Throwable ex) {
super(msg, ex);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package mju.iphak.maru_egg.common.exception.custom.webClient;

import org.springframework.web.reactive.function.client.WebClientException;

public class InternalServerErrorWebClientException extends WebClientException {
public InternalServerErrorWebClientException(final String msg) {
super(msg);
}

public InternalServerErrorWebClientException(final String msg, final Throwable ex) {
super(msg, ex);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package mju.iphak.maru_egg.common.exception.custom.webClient;

import org.springframework.web.reactive.function.client.WebClientException;

public class NotFoundWebClientException extends WebClientException {
public NotFoundWebClientException(final String msg) {
super(msg);
}

public NotFoundWebClientException(final String msg, final Throwable ex) {
super(msg, ex);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@ public QuestionResponse question(final QuestionType type, final QuestionCategory

private QuestionResponse askNewQuestion(QuestionType type, QuestionCategory category, String content,
String contentToken) {
LLMAskQuestionRequest askQuestionRequest = LLMAskQuestionRequest.of(type.toString(), category.toString(),
LLMAskQuestionRequest askQuestionRequest = LLMAskQuestionRequest.of(type.toString(),
isCategoryNullThen(category),
content);

LLMAnswerResponse llmAnswerResponse = answerService.askQuestion(askQuestionRequest).block();
Expand All @@ -70,6 +71,13 @@ private QuestionResponse askNewQuestion(QuestionType type, QuestionCategory cate
return createQuestionResponse(newQuestion, newAnswer);
}

private static String isCategoryNullThen(final QuestionCategory category) {
if (category.toString() == null) {
return QuestionCategory.UNCLASSIFIED.getQuestionCategory();
}
return category.toString();
}

private Answer saveAnswer(final Question question, final String content) {
Answer newAnswer = Answer.of(question, content);
return answerService.saveAnswer(newAnswer);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public enum QuestionCategory {
PAST_QUESTIONS("기출문제"),
UNIV_LIFE("대학생활"),
INTERVIEW_PRACTICAL_TEST("면접/실기"),
ETC("기타");
UNCLASSIFIED("미분류");

private final String questionCategory;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public record QuestionRequest(
@NotNull(message = "질문 타입은 비어있을 수 없습니다.")
QuestionType type,

@Schema(description = "질문 카테고리(모집요강, 입시결과, 기출 문제)")
@Schema(description = "질문 카테고리(모집요강, 입시결과, 기출 문제)", nullable = true)
QuestionCategory category,

@Schema(description = "질문 내용")
Expand Down

0 comments on commit 8b42c4e

Please sign in to comment.