refactor: AnalysisCompletedHandler 책임 분리#81
Conversation
There was a problem hiding this comment.
Code Review
This pull request refactors the interview feedback logic by reorganizing DTOs into specialized subpackages and delegating processing logic to the new AnalysisCompletionService and SessionCompletionNotifier. It also decouples prompt generation by splitting PromptBuilder into QuestionPromptBuilder and FeedbackPromptBuilder. The review feedback points out a potential race condition in the session completion trigger and recommends adding a merge function to a Collectors.toMap operation to prevent potential exceptions from duplicate keys.
| private void completeSessionIfReady(InterviewAnswer answer) { | ||
| InterviewSession session = getSession(answer); | ||
| if (session == null) { | ||
| log.warn("[최종평가] 세션 없음 - answerId: {}", answer.getId()); | ||
| return; | ||
| } | ||
|
|
||
| if (!isFinalFeedbackReady(session)) { | ||
| return; | ||
| } |
There was a problem hiding this comment.
There is a potential race condition in completeSessionIfReady. If multiple answers for the same session complete their analysis simultaneously, multiple threads might pass the isFinalFeedbackReady check and proceed to call the expensive OpenAI API (feedbackGenerator.generateFinal) and trigger session completion notifications multiple times.
Consider adding a check to verify if the session is already completed or using a synchronization mechanism (like a distributed lock or an atomic status update in the database) to ensure that the final evaluation logic is executed exactly once per session.
|
|
||
| private Map<UUID, InterviewAnswer> getAnswerMap(UUID sessionId) { | ||
| return answerRepository.findBySessionId(sessionId).stream() | ||
| .collect(Collectors.toMap(a -> a.getInterviewQuestion().getId(), a -> a)); |
There was a problem hiding this comment.
Using Collectors.toMap without a merge function will throw an IllegalStateException if duplicate keys are encountered. While the business logic might currently ensure one answer per question per session, it is safer to provide a merge function or use groupingBy if multiple answers could ever exist (e.g., due to retries or future changes).
| .collect(Collectors.toMap(a -> a.getInterviewQuestion().getId(), a -> a)); | |
| .collect(Collectors.toMap(a -> a.getInterviewQuestion().getId(), a -> a, (existing, replacement) -> existing)); |
📌 관련 이슈 (Related Issue)
📝 작업 내용 (Description)
🔄 변경 유형 (Type of Change)
✅ 체크리스트 (Checklist)