diff --git a/cs25-batch/src/main/java/com/example/cs25batch/aop/MailLogAspect.java b/cs25-batch/src/main/java/com/example/cs25batch/aop/MailLogAspect.java index 2b50daec..89d00a0b 100644 --- a/cs25-batch/src/main/java/com/example/cs25batch/aop/MailLogAspect.java +++ b/cs25-batch/src/main/java/com/example/cs25batch/aop/MailLogAspect.java @@ -48,7 +48,7 @@ public Object logMailSend(ProceedingJoinPoint joinPoint) throws Throwable { caused = e.getMessage(); throw new CustomMailException(MailExceptionCode.EMAIL_SEND_FAILED_ERROR); } finally { - MailLog log = MailLog.builder() + MailLog mailLog = MailLog.builder() .subscription(subscription) .quiz(quiz) .sendDate(LocalDateTime.now()) @@ -56,10 +56,11 @@ public Object logMailSend(ProceedingJoinPoint joinPoint) throws Throwable { .caused(caused) .build(); - mailLogRepository.save(log); + mailLogRepository.save(mailLog); mailLogRepository.flush(); if (status == MailStatus.FAILED) { + log.info("메일 발송 실패 : subscriptionId - {}, cause - {}", subscription.getId(), caused); Map retryMessage = Map.of( "email", subscription.getEmail(), "subscriptionId", subscription.getId().toString(), diff --git a/cs25-entity/src/main/java/com/example/cs25entity/domain/mail/repository/MailLogRepository.java b/cs25-entity/src/main/java/com/example/cs25entity/domain/mail/repository/MailLogRepository.java index a9184764..3431079d 100644 --- a/cs25-entity/src/main/java/com/example/cs25entity/domain/mail/repository/MailLogRepository.java +++ b/cs25-entity/src/main/java/com/example/cs25entity/domain/mail/repository/MailLogRepository.java @@ -7,6 +7,8 @@ import java.util.Optional; import java.util.Set; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; @Repository @@ -23,5 +25,11 @@ default MailLog findByIdOrElseThrow(Long id) { void deleteAllByIdIn(Collection ids); - Set findDistinctQuiz_IdBySubscription_Id(Long subscriptionId); + @Query(""" + select distinct ml.quiz.id + from MailLog ml + where ml.subscription.id = :subscriptionId + and ml.status = com.example.cs25entity.domain.mail.enums.MailStatus.SENT + """) + Set findDistinctQuiz_IdBySubscription_Id(@Param("subscriptionId") Long subscriptionId); } diff --git a/cs25-service/Dockerfile b/cs25-service/Dockerfile index 65fd9b67..dc2c1800 100644 --- a/cs25-service/Dockerfile +++ b/cs25-service/Dockerfile @@ -20,6 +20,14 @@ LABEL type="application" module="cs25-service" # 작업 디렉토리 WORKDIR /apps +# Node.js + npm 설치 후, MCP 서버 전역 설치 +RUN apt-get update && apt-get install -y curl ca-certificates gnupg \ + && curl -fsSL https://deb.nodesource.com/setup_20.x | bash - \ + && apt-get install -y nodejs \ + && npm install -g @modelcontextprotocol/server-brave-search \ + && node -v && npm -v && which server-brave-search \ + && apt-get clean && rm -rf /var/lib/apt/lists/* + # jar 복사 COPY --from=builder /build/cs25-service/build/libs/*.jar app.jar diff --git a/cs25-service/src/main/java/com/example/cs25service/domain/ai/service/AiFeedbackStreamProcessor.java b/cs25-service/src/main/java/com/example/cs25service/domain/ai/service/AiFeedbackStreamProcessor.java index d9eee6cc..c159fb6d 100644 --- a/cs25-service/src/main/java/com/example/cs25service/domain/ai/service/AiFeedbackStreamProcessor.java +++ b/cs25-service/src/main/java/com/example/cs25service/domain/ai/service/AiFeedbackStreamProcessor.java @@ -4,6 +4,8 @@ import com.example.cs25entity.domain.user.repository.UserRepository; import com.example.cs25entity.domain.userQuizAnswer.repository.UserQuizAnswerRepository; import com.example.cs25service.domain.ai.client.AiChatClient; +//import com.example.cs25service.domain.ai.exception.AiException; +//import com.example.cs25service.domain.ai.exception.AiExceptionCode; import com.example.cs25service.domain.ai.prompt.AiPromptProvider; import com.fasterxml.jackson.databind.JsonNode; import java.io.IOException; @@ -89,9 +91,9 @@ public void stream(Long answerId, SseEmitter emitter) { send(emitter, "[종료]"); String feedback = fullFeedbackBuffer.toString(); - if (feedback == null || feedback.isEmpty()) { - throw new AiException(AiExceptionCode.INTERNAL_SERVER_ERROR); - } +// if (feedback == null || feedback.isEmpty()) { +// throw new AiException(AiExceptionCode.INTERNAL_SERVER_ERROR); +// } boolean isCorrect = isCorrect(feedback); diff --git a/cs25-service/src/main/resources/application.properties b/cs25-service/src/main/resources/application.properties index 7fa42814..9da7b156 100644 --- a/cs25-service/src/main/resources/application.properties +++ b/cs25-service/src/main/resources/application.properties @@ -68,10 +68,9 @@ spring.ai.mcp.client.type=SYNC spring.ai.mcp.client.request-timeout=30s spring.ai.mcp.client.root-change-notification=false # STDIO Connect: Brave Search -spring.ai.mcp.client.stdio.connections.brave.command=npx -spring.ai.mcp.client.stdio.connections.brave.args[0]=-y -spring.ai.mcp.client.stdio.connections.brave.args[1]=@modelcontextprotocol/server-brave-search +spring.ai.mcp.client.stdio.connections.brave.command=server-brave-search spring.ai.mcp.client.stdio.connections.brave.env.BRAVE_API_KEY=${BRAVE_API_KEY} +spring.ai.mcp.client.initialized=false #MAIL spring.mail.host=smtp.gmail.com spring.mail.port=587