Skip to content

Commit a32175f

Browse files
committed
fix: TTS 콜백 알림 발행 경로 정리
1 parent fed1845 commit a32175f

2 files changed

Lines changed: 26 additions & 12 deletions

File tree

backend/src/main/java/com/stackup/stackup/session/application/TtsCallbackService.java

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import com.stackup.stackup.common.messaging.domain.ProcessedMessage;
44
import com.stackup.stackup.common.messaging.domain.ProcessedMessageRepository;
5-
import com.stackup.stackup.common.sse.SseEventPublisher;
5+
import com.stackup.stackup.common.messaging.RealtimeNotifyEvent;
66
import com.stackup.stackup.common.sse.SseEventType;
77
import com.stackup.stackup.session.application.dto.TtsCallbackEnvelope;
88
import com.stackup.stackup.session.application.dto.TtsCallbackPayload;
@@ -13,6 +13,7 @@
1313
import lombok.RequiredArgsConstructor;
1414
import org.slf4j.Logger;
1515
import org.slf4j.LoggerFactory;
16+
import org.springframework.context.ApplicationEventPublisher;
1617
import org.springframework.dao.DataIntegrityViolationException;
1718
import org.springframework.stereotype.Service;
1819
import org.springframework.transaction.annotation.Transactional;
@@ -27,7 +28,7 @@ public class TtsCallbackService {
2728

2829
private final InterviewMessageRepository messageRepository;
2930
private final ProcessedMessageRepository processedMessageRepository;
30-
private final SseEventPublisher sseEventPublisher;
31+
private final ApplicationEventPublisher events;
3132

3233
@Transactional
3334
public void apply(TtsCallbackEnvelope envelope) {
@@ -94,9 +95,9 @@ private void publishNotice(InterviewMessage message, String errorCode) {
9495
message.getTtsDurationSec(),
9596
errorCode
9697
);
97-
sseEventPublisher.publishToSession(sessionId, SseEventType.SESSION_MESSAGE, notice);
98-
sseEventPublisher.publishToUser(message.getSession().getUser().getId(),
99-
SseEventType.SESSION_MESSAGE, notice);
98+
events.publishEvent(RealtimeNotifyEvent.session(sessionId, SseEventType.SESSION_MESSAGE, notice));
99+
events.publishEvent(RealtimeNotifyEvent.user(message.getSession().getUser().getId(),
100+
SseEventType.SESSION_MESSAGE, notice));
100101
}
101102

102103
private boolean isProcessed(String messageId) {

backend/src/test/java/com/stackup/stackup/session/application/TtsCallbackServiceTest.java

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,15 @@
22

33
import static org.assertj.core.api.Assertions.assertThat;
44
import static org.mockito.ArgumentMatchers.any;
5-
import static org.mockito.ArgumentMatchers.eq;
5+
import static org.mockito.ArgumentMatchers.argThat;
66
import static org.mockito.Mockito.never;
77
import static org.mockito.Mockito.verify;
88
import static org.mockito.Mockito.when;
99

1010
import com.fasterxml.jackson.databind.ObjectMapper;
11+
import com.stackup.stackup.common.messaging.RealtimeNotifyEvent;
1112
import com.stackup.stackup.common.messaging.domain.ProcessedMessage;
1213
import com.stackup.stackup.common.messaging.domain.ProcessedMessageRepository;
13-
import com.stackup.stackup.common.sse.SseEventPublisher;
1414
import com.stackup.stackup.common.sse.SseEventType;
1515
import com.stackup.stackup.session.application.dto.MessageResult;
1616
import com.stackup.stackup.session.application.dto.TtsCallbackEnvelope;
@@ -28,6 +28,7 @@
2828
import org.mockito.InjectMocks;
2929
import org.mockito.Mock;
3030
import org.mockito.junit.jupiter.MockitoExtension;
31+
import org.springframework.context.ApplicationEventPublisher;
3132
import org.springframework.test.util.ReflectionTestUtils;
3233

3334
@ExtendWith(MockitoExtension.class)
@@ -37,7 +38,7 @@ class TtsCallbackServiceTest {
3738

3839
@Mock InterviewMessageRepository messageRepository;
3940
@Mock ProcessedMessageRepository processedMessageRepository;
40-
@Mock SseEventPublisher sseEventPublisher;
41+
@Mock ApplicationEventPublisher events;
4142
@InjectMocks TtsCallbackService service;
4243

4344
@Test
@@ -57,8 +58,10 @@ void apply_successStoresTtsFieldsWithoutChangingMessageStatus() {
5758
assertThat(question.getTtsAudioPath()).isEqualTo("interview/tts/50/100.mp3");
5859
assertThat(question.getTtsDurationSec()).isEqualTo(2.4);
5960
assertThat(MessageResult.of(question).ttsAudioPath()).isEqualTo("interview/tts/50/100.mp3");
60-
verify(sseEventPublisher).publishToSession(eq(50L), eq(SseEventType.SESSION_MESSAGE), any());
61-
verify(sseEventPublisher).publishToUser(eq(1L), eq(SseEventType.SESSION_MESSAGE), any());
61+
verify(events).publishEvent(argThat(event ->
62+
isNotice(event, RealtimeNotifyEvent.Channel.SESSION, 50L)));
63+
verify(events).publishEvent(argThat(event ->
64+
isNotice(event, RealtimeNotifyEvent.Channel.USER, 1L)));
6265
verify(processedMessageRepository).save(any(ProcessedMessage.class));
6366
}
6467

@@ -78,7 +81,8 @@ void apply_failedMarksOnlyTtsFailedAndLeavesQuestionUsable() {
7881
assertThat(question.getTtsStatus()).isEqualTo(TtsStatus.FAILED);
7982
assertThat(question.getContent()).isEqualTo("Q?");
8083
assertThat(question.getTtsAudioPath()).isNull();
81-
verify(sseEventPublisher).publishToSession(eq(50L), eq(SseEventType.SESSION_MESSAGE), any());
84+
verify(events).publishEvent(argThat(event ->
85+
isNotice(event, RealtimeNotifyEvent.Channel.SESSION, 50L)));
8286
verify(processedMessageRepository).save(any(ProcessedMessage.class));
8387
}
8488

@@ -96,7 +100,7 @@ void apply_ignoresIntervieweeMessages() {
96100
)));
97101

98102
assertThat(answer.getTtsStatus()).isEqualTo(TtsStatus.NOT_REQUESTED);
99-
verify(sseEventPublisher, never()).publishToSession(any(), any(), any());
103+
verify(events, never()).publishEvent(any());
100104
verify(processedMessageRepository).save(any(ProcessedMessage.class));
101105
}
102106

@@ -132,6 +136,15 @@ private TtsCallbackEnvelope envelope(String messageId, TtsCallbackPayload payloa
132136
null, "ai", payload, null);
133137
}
134138

139+
private boolean isNotice(Object event, RealtimeNotifyEvent.Channel channel, Long id) {
140+
if (!(event instanceof RealtimeNotifyEvent realtimeNotifyEvent)) {
141+
return false;
142+
}
143+
return realtimeNotifyEvent.channel() == channel
144+
&& realtimeNotifyEvent.id().equals(id)
145+
&& realtimeNotifyEvent.type() == SseEventType.SESSION_MESSAGE;
146+
}
147+
135148
private InterviewSession sessionFixture(Long id) {
136149
User user = User.createGithubUser(1L, "u", null, null, "t");
137150
ReflectionTestUtils.setField(user, "id", 1L);

0 commit comments

Comments
 (0)