Skip to content

Commit ac49761

Browse files
committed
refactor: AnswerPersistenceService 네이밍 및 구조 정리
1 parent aec3529 commit ac49761

3 files changed

Lines changed: 40 additions & 47 deletions

File tree

src/main/java/io/wisoft/prepair/prepair_api/service/answer/AnswerPersistenceService.java

Lines changed: 37 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -30,25 +30,55 @@
3030
@Slf4j
3131
@Service
3232
@RequiredArgsConstructor
33+
@Transactional
3334
public class AnswerPersistenceService {
3435

3536
private final QuestionRepository questionRepository;
3637
private final AnswerRepository answerRepository;
3738
private final FeedbackRepository feedbackRepository;
3839
private final ObjectMapper objectMapper;
3940

40-
@Transactional
41-
public AnswerSubmitResult saveAnswerAndFeedback(final UUID questionId, final UUID memberId, final String answer, final FeedbackResult result, final FeedbackDetail detail) {
41+
public AnswerSubmitResult saveAnswerAndFeedback(final UUID questionId, final UUID memberId, final String answerText, final FeedbackResult result, final FeedbackDetail detail) {
4242
InterviewQuestion question = getQuestion(questionId, memberId);
4343
question.updateStatus(QuestionStatus.ANSWERED);
4444

45-
InterviewAnswer interviewAnswer = saveAnswer(answer, question);
46-
InterviewFeedback feedback = saveFeedback(result, detail, interviewAnswer);
45+
// 답변 + 피드백 저장
46+
InterviewAnswer answer = saveAnswer(answerText, question);
47+
InterviewFeedback feedback = saveTextFeedback(result, detail, answer);
48+
49+
// 조건부 UPDATE로 최초 답변 여부 원자적 판단 (race condition 방지)
4750
boolean firstAnswer = isFirstTodayAnswer(questionId, feedback.getScore());
4851

52+
// sendScore는 트랜잭션 외부에서 호출하므로 firstAnswer를 함께 반환
4953
return new AnswerSubmitResult(feedback, firstAnswer);
5054
}
5155

56+
public InterviewAnswer saveVideoAnswer(final UUID questionId, final UUID memberId) {
57+
InterviewQuestion question = getQuestion(questionId, memberId);
58+
question.updateStatus(QuestionStatus.ANSWERED);
59+
return answerRepository.save(new InterviewAnswer(question, "", AnswerType.VIDEO, null));
60+
}
61+
62+
public void updateMediaUrl(final UUID answerId, final String mediaUrl) {
63+
InterviewAnswer interviewAnswer = getAnswer(answerId);
64+
interviewAnswer.updateMediaUrl(mediaUrl);
65+
}
66+
67+
public void updateAnswer(final UUID answerId, final String answer) {
68+
InterviewAnswer interviewAnswer = getAnswer(answerId);
69+
interviewAnswer.updateAnswer(answer);
70+
}
71+
72+
public void saveVideoFeedback(final UUID answerId, final FeedbackResult result, final FeedbackDetail detail, final FeedbackType feedbackType) {
73+
InterviewAnswer interviewAnswer = getAnswer(answerId);
74+
feedbackRepository.save(new InterviewFeedback(interviewAnswer, serializeFeedback(detail), feedbackType, result.score()));
75+
}
76+
77+
public void saveCombinedFeedback(final UUID answerId, final CombinedFeedbackResult result) {
78+
InterviewAnswer interviewAnswer = getAnswer(answerId);
79+
feedbackRepository.save(new InterviewFeedback(interviewAnswer, result.combineFeedback(), FeedbackType.COMBINED, result.score()));
80+
}
81+
5282
private InterviewQuestion getQuestion(UUID questionId, UUID memberId) {
5383
return questionRepository.findByIdAndMemberId(questionId, memberId)
5484
.orElseThrow(() -> new BusinessException(ErrorCode.QUESTION_NOT_FOUND));
@@ -60,7 +90,7 @@ private InterviewAnswer saveAnswer(String answer, InterviewQuestion question) {
6090
);
6191
}
6292

63-
private InterviewFeedback saveFeedback(FeedbackResult result, FeedbackDetail detail, InterviewAnswer interviewAnswer) {
93+
private InterviewFeedback saveTextFeedback(FeedbackResult result, FeedbackDetail detail, InterviewAnswer interviewAnswer) {
6494
return feedbackRepository.save(
6595
new InterviewFeedback(interviewAnswer, serializeFeedback(detail), FeedbackType.TEXT, result.score())
6696
);
@@ -72,46 +102,9 @@ private boolean isFirstTodayAnswer(final UUID questionId, final Integer score) {
72102
return questionRepository.updateLatestScoreIfFirstTime(questionId, score, startOfDay, endOfDay) > 0;
73103
}
74104

75-
@Transactional
76-
public InterviewAnswer createVideoAnswer(final UUID questionId, final UUID memberId) {
77-
InterviewQuestion question = getQuestion(questionId, memberId);
78-
question.updateStatus(QuestionStatus.ANSWERED);
79-
80-
return answerRepository.save(
81-
new InterviewAnswer(question, "", AnswerType.VIDEO, null));
82-
}
83-
84-
@Transactional
85-
public void updateMediaUrl(final UUID answerId, final String mediaUrl) {
86-
InterviewAnswer interviewAnswer = answerRepository.findById(answerId)
87-
.orElseThrow(() -> new BusinessException(ErrorCode.ANSWER_NOT_FOUND));
88-
interviewAnswer.updateMediaUrl(mediaUrl);
89-
}
90-
91-
@Transactional
92-
public void updateAnswer(final UUID answerId, final String answer) {
93-
InterviewAnswer interviewAnswer = answerRepository.findById(answerId)
94-
.orElseThrow(() -> new BusinessException(ErrorCode.ANSWER_NOT_FOUND));
95-
interviewAnswer.updateAnswer(answer);
96-
}
97-
98-
@Transactional
99-
public void saveFeedback(final UUID answerId, final FeedbackResult result,
100-
final FeedbackDetail detail, final FeedbackType feedbackType) {
101-
InterviewAnswer interviewAnswer = answerRepository.findById(answerId)
102-
.orElseThrow(() -> new BusinessException(ErrorCode.ANSWER_NOT_FOUND));
103-
104-
feedbackRepository.save(
105-
new InterviewFeedback(interviewAnswer, serializeFeedback(detail), feedbackType, result.score()));
106-
}
107-
108-
@Transactional
109-
public void saveCombinedFeedback(final UUID answerId, final CombinedFeedbackResult result) {
110-
InterviewAnswer interviewAnswer = answerRepository.findById(answerId)
105+
private InterviewAnswer getAnswer(UUID answerId) {
106+
return answerRepository.findById(answerId)
111107
.orElseThrow(() -> new BusinessException(ErrorCode.ANSWER_NOT_FOUND));
112-
113-
feedbackRepository.save(
114-
new InterviewFeedback(interviewAnswer, result.combineFeedback(), FeedbackType.COMBINED, result.score()));
115108
}
116109

117110
private String serializeFeedback(final FeedbackDetail detail) {

src/main/java/io/wisoft/prepair/prepair_api/service/answer/AnswerService.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ public void submitVideoAnswer(final UUID questionId, final UUID memberId, final
5858

5959
// 임시 파일 먼저 생성 후 DB 저장 (실패 시 고아 레코드 방지)
6060
Path videoPath = createTempFile(video);
61-
InterviewAnswer answer = answerPersistenceService.createVideoAnswer(questionId, memberId);
61+
InterviewAnswer answer = answerPersistenceService.saveVideoAnswer(questionId, memberId);
6262

6363
// 3개 비동기 작업 모두 완료 시 이벤트 발행을 위한 트래커 초기화
6464
completionTracker.init(answer.getId(), videoPath);

src/main/java/io/wisoft/prepair/prepair_api/service/answer/VideoAnswerAnalyzer.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ public void analyzeSTT(final UUID answerId, final UUID questionId, final UUID me
5757
FeedbackResult result = feedbackGenerator.generate(question, answer);
5858
FeedbackDetail detail = new FeedbackDetail(result.good(), result.improvement(), result.recommendation());
5959

60-
answerPersistenceService.saveFeedback(answerId, result, detail, FeedbackType.STT);
60+
answerPersistenceService.saveVideoFeedback(answerId, result, detail, FeedbackType.STT);
6161
log.info("[VIDEO-STT] 분석 완료 - answerId: {}", answerId);
6262
completionTracker.complete(answerId);
6363
} catch (Exception e) {
@@ -72,7 +72,7 @@ public void analyzeVideo(final UUID answerId, final Path videoPath) {
7272
FeedbackResult result = videoAnalysisService.analyze(videoPath);
7373
FeedbackDetail detail = new FeedbackDetail(result.good(), result.improvement(), result.recommendation());
7474

75-
answerPersistenceService.saveFeedback(answerId, result, detail, FeedbackType.VIDEO);
75+
answerPersistenceService.saveVideoFeedback(answerId, result, detail, FeedbackType.VIDEO);
7676
log.info("[VIDEO-ANALYSIS] 분석 완료 - answerId: {}", answerId);
7777
completionTracker.complete(answerId);
7878
} catch (Exception e) {

0 commit comments

Comments
 (0)