-
Notifications
You must be signed in to change notification settings - Fork 1
refactor : 알림/채팅 Redis 발행 안정성 및 예외 처리 개선 #155
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
94b4cd7
1284857
fc5ff71
2d51667
b963c9f
77bdf45
96d87fc
031791a
ae81b27
14350bc
5efc1b1
3c71556
c0c0345
972f5af
761d298
bf43b7e
a310cb4
720feff
a3642c4
e3ed193
8c31e08
a054172
ba2771a
de0c260
e037390
ffe4c6a
daf7fb9
94183f2
c36084b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -37,7 +37,7 @@ public class ChatService { | |
| private final UserRepository userRepository; | ||
| private final StringRedisTemplate redisTemplate; | ||
| private final NotificationService notificationService; | ||
| private final ObjectMapper objectMapper = new ObjectMapper(); | ||
| private final ObjectMapper objectMapper; | ||
|
|
||
| private static final String CHAT_CHANNEL_PREFIX = "chat:room:"; | ||
|
|
||
|
|
@@ -189,8 +189,9 @@ public void deleteMessages(Long roomId, Long userId, List<Long> messageIds) { | |
| * Redis Pub/Sub을 통해 메시지 발행 | ||
| */ | ||
| public void publishToRedis(ChatMessage message) { | ||
| Long roomId = message.getChatRoom().getId(); | ||
| ChatPayloadResponseDto payload = ChatPayloadResponseDto.builder() | ||
| .roomId(message.getChatRoom().getId()) | ||
| .roomId(roomId) | ||
| .messageId(message.getId()) | ||
| .senderId(message.getSenderId()) | ||
| .senderRole(message.getSenderRole().name()) | ||
|
|
@@ -203,11 +204,12 @@ public void publishToRedis(ChatMessage message) { | |
|
|
||
| try { | ||
| String json = objectMapper.writeValueAsString(payload); | ||
| String channel = CHAT_CHANNEL_PREFIX + message.getChatRoom().getId(); | ||
| String channel = CHAT_CHANNEL_PREFIX + roomId; | ||
| redisTemplate.convertAndSend(channel, json); | ||
| log.info("Redis 메시지 발행: channel={}, messageId={}", channel, message.getId()); | ||
| } catch (JsonProcessingException e) { | ||
| log.error("ChatPayload 직렬화 실패", e); | ||
| log.error("채팅 메시지 직렬화 실패: roomId={}, messageId={}", roomId, message.getId(), e); | ||
| throw new ChatPublishFailedException(roomId); | ||
| } | ||
|
Comment on lines
205
to
213
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. PR 설명에 언급된 'Transactional Outbox 패턴'이 채팅 메시지 발행에는 적용되지 않았습니다. 현재 구현 방식은 |
||
| } | ||
|
|
||
|
|
@@ -228,7 +230,8 @@ public void publishReadEvent(Long roomId, Long userId, Long lastReadMessageId) { | |
| redisTemplate.convertAndSend(channel, json); | ||
| log.info("읽음 이벤트 발행: channel={}, readerId={}", channel, userId); | ||
| } catch (JsonProcessingException e) { | ||
| log.error("읽음 이벤트 직렬화 실패", e); | ||
| log.error("읽음 이벤트 직렬화 실패: roomId={}, userId={}", roomId, userId, e); | ||
| throw new ChatPublishFailedException(roomId); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| } | ||
|
Comment on lines
232
to
235
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| } | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| package org.swyp.linkit.global.error.exception; | ||
|
|
||
| import org.swyp.linkit.global.error.ErrorCode; | ||
| import org.swyp.linkit.global.error.exception.base.BusinessException; | ||
|
|
||
| public class ChatPublishFailedException extends BusinessException { | ||
|
|
||
| public ChatPublishFailedException() { | ||
| super(ErrorCode.CHAT_PUBLISH_FAILED); | ||
| } | ||
|
|
||
| public ChatPublishFailedException(Long roomId) { | ||
| super(ErrorCode.CHAT_PUBLISH_FAILED, | ||
| "채팅 메시지 발행에 실패했습니다. roomId=" + roomId); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| package org.swyp.linkit.global.error.exception; | ||
|
|
||
| import org.swyp.linkit.global.error.ErrorCode; | ||
| import org.swyp.linkit.global.error.exception.base.BusinessException; | ||
|
|
||
| public class NotificationPublishFailedException extends BusinessException { | ||
|
|
||
| public NotificationPublishFailedException() { | ||
| super(ErrorCode.NOTIFICATION_PUBLISH_FAILED); | ||
| } | ||
|
|
||
| public NotificationPublishFailedException(Long notificationId) { | ||
| super(ErrorCode.NOTIFICATION_PUBLISH_FAILED, | ||
| "알림 발행에 실패했습니다. notificationId=" + notificationId); | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ChatPublishFailedException을 던져 STOMP ERROR 프레임을 전달하고자 하는 의도는 확인되나,afterCommit패턴을 적용할 경우 트랜잭션 완료 후 예외가 발생하므로 클라이언트에게 에러 전달이 어려울 수 있습니다. 프로젝트 규칙에 따라, 트랜잭션 롤백과 관련된 복잡한 예외 처리나 상태 업데이트(FAILED 등) 대신, 스케줄러를 통한 재시도 메커니즘을 활용하여 처리를 단순화하는 것을 권장합니다.References