From 6f292ebfe9c9e58c38e197affecdb2587a608d79 Mon Sep 17 00:00:00 2001 From: rt3310 Date: Sat, 13 Sep 2025 00:11:31 +0900 Subject: [PATCH] =?UTF-8?q?fix[#320]:=20=EB=8D=B0=EC=9D=B4=ED=84=B0=20?= =?UTF-8?q?=EC=A0=84=EC=86=A1=20=EC=8B=A4=ED=8C=A8=20=EC=8B=9C=20SseEmitte?= =?UTF-8?q?r=20=EC=82=AD=EC=A0=9C=20=EB=B0=8F=20=EC=99=84=EB=A3=8C=20?= =?UTF-8?q?=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../recordit/invite/service/InviteService.java | 4 +--- .../member/service/MemberFollowService.java | 3 +-- .../pushalarm/job/ScheduleAlarmJob.java | 10 +--------- .../pushalarm/service/AlarmService.java | 4 +--- .../pushalarm/service/SseEmitterManager.java | 17 +++++++++++++---- .../service/SseEmitterManagerTest.java | 5 ++--- 6 files changed, 19 insertions(+), 24 deletions(-) diff --git a/src/main/java/com/sillim/recordit/invite/service/InviteService.java b/src/main/java/com/sillim/recordit/invite/service/InviteService.java index d98fc15a..042e9506 100644 --- a/src/main/java/com/sillim/recordit/invite/service/InviteService.java +++ b/src/main/java/com/sillim/recordit/invite/service/InviteService.java @@ -14,7 +14,6 @@ import com.sillim.recordit.member.domain.Member; import com.sillim.recordit.pushalarm.dto.PushMessage; import com.sillim.recordit.pushalarm.service.AlarmService; -import java.io.IOException; import java.time.LocalDateTime; import java.util.Base64; import java.util.Optional; @@ -75,8 +74,7 @@ public InviteLink searchInviteInfo(String inviteCode) { new String(Base64.getUrlDecoder().decode(inviteCode))); } - public void inviteMember(Long calendarId, Long invitedMemberId, Member inviter) - throws IOException { + public void inviteMember(Long calendarId, Long invitedMemberId, Member inviter) { Calendar calendar = calendarQueryService.searchByCalendarId(calendarId); calendar.validateAuthenticatedMember(inviter.getId()); diff --git a/src/main/java/com/sillim/recordit/member/service/MemberFollowService.java b/src/main/java/com/sillim/recordit/member/service/MemberFollowService.java index 243fcddb..375b9b66 100644 --- a/src/main/java/com/sillim/recordit/member/service/MemberFollowService.java +++ b/src/main/java/com/sillim/recordit/member/service/MemberFollowService.java @@ -7,7 +7,6 @@ import com.sillim.recordit.pushalarm.dto.PushMessage; import com.sillim.recordit.pushalarm.service.AlarmService; import jakarta.persistence.OptimisticLockException; -import java.io.IOException; import lombok.RequiredArgsConstructor; import org.hibernate.StaleObjectStateException; import org.springframework.orm.ObjectOptimisticLockingFailureException; @@ -33,7 +32,7 @@ public class MemberFollowService { }, maxAttempts = 15, backoff = @Backoff(delay = 30)) - public void follow(Long followerId, Long followedId) throws IOException { + public void follow(Long followerId, Long followedId) { Member follower = memberQueryService.findByMemberId(followerId); Member followed = memberQueryService.findByMemberId(followedId); diff --git a/src/main/java/com/sillim/recordit/pushalarm/job/ScheduleAlarmJob.java b/src/main/java/com/sillim/recordit/pushalarm/job/ScheduleAlarmJob.java index 353ff735..c452d300 100644 --- a/src/main/java/com/sillim/recordit/pushalarm/job/ScheduleAlarmJob.java +++ b/src/main/java/com/sillim/recordit/pushalarm/job/ScheduleAlarmJob.java @@ -4,11 +4,8 @@ import com.google.firebase.messaging.FirebaseMessagingException; import com.google.firebase.messaging.Message; import com.google.firebase.messaging.Notification; -import com.sillim.recordit.global.exception.ErrorCode; -import com.sillim.recordit.global.exception.common.ApplicationException; import com.sillim.recordit.pushalarm.dto.PushMessage; import com.sillim.recordit.pushalarm.service.AlarmService; -import java.io.IOException; import java.util.List; import lombok.extern.slf4j.Slf4j; import org.quartz.Job; @@ -50,11 +47,6 @@ public void execute(JobExecutionContext context) { } }); - try { - alarmService.pushAlarm( - -1L, memberId, PushMessage.fromSchedule(scheduleId, title, body)); - } catch (IOException e) { - throw new ApplicationException(ErrorCode.UNHANDLED_EXCEPTION, e.getMessage()); - } + alarmService.pushAlarm(-1L, memberId, PushMessage.fromSchedule(scheduleId, title, body)); } } diff --git a/src/main/java/com/sillim/recordit/pushalarm/service/AlarmService.java b/src/main/java/com/sillim/recordit/pushalarm/service/AlarmService.java index 64f1984f..d5752198 100644 --- a/src/main/java/com/sillim/recordit/pushalarm/service/AlarmService.java +++ b/src/main/java/com/sillim/recordit/pushalarm/service/AlarmService.java @@ -3,7 +3,6 @@ import com.sillim.recordit.pushalarm.domain.AlarmLog; import com.sillim.recordit.pushalarm.dto.PushMessage; import com.sillim.recordit.pushalarm.repository.AlarmLogRepository; -import java.io.IOException; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -15,8 +14,7 @@ public class AlarmService { private final SseEmitterManager sseEmitterManager; private final AlarmLogRepository alarmLogRepository; - public boolean pushAlarm(Long senderId, Long receiverId, PushMessage message) - throws IOException { + public boolean pushAlarm(Long senderId, Long receiverId, PushMessage message) { AlarmLog alarmLog = alarmLogRepository.save( AlarmLog.builder() diff --git a/src/main/java/com/sillim/recordit/pushalarm/service/SseEmitterManager.java b/src/main/java/com/sillim/recordit/pushalarm/service/SseEmitterManager.java index dc3e2c5d..e60591dd 100644 --- a/src/main/java/com/sillim/recordit/pushalarm/service/SseEmitterManager.java +++ b/src/main/java/com/sillim/recordit/pushalarm/service/SseEmitterManager.java @@ -10,10 +10,13 @@ @Slf4j @Service public class SseEmitterManager { + + private static final Long TIMEOUT = 60L * 60 * 1000; + private final ConcurrentHashMap clients = new ConcurrentHashMap<>(); public SseEmitter subscribe(Long memberId) { - SseEmitter emitter = new SseEmitter(Long.MAX_VALUE); + SseEmitter emitter = new SseEmitter(TIMEOUT); clients.put(memberId, emitter); emitter.onCompletion(() -> clients.remove(memberId)); @@ -24,12 +27,18 @@ public SseEmitter subscribe(Long memberId) { return emitter; } - public boolean sendToClient(Long memberId, PushMessage message) throws IOException { + public boolean sendToClient(Long memberId, PushMessage message) { SseEmitter emitter = clients.get(memberId); if (emitter != null) { - emitter.send(SseEmitter.event().name(message.type().name()).data(message)); - return true; + try { + emitter.send(SseEmitter.event().name(message.type().name()).data(message)); + return true; + } catch (IOException exception) { + clients.remove(memberId); + emitter.completeWithError(exception); + return false; + } } return false; } diff --git a/src/test/java/com/sillim/recordit/pushalarm/service/SseEmitterManagerTest.java b/src/test/java/com/sillim/recordit/pushalarm/service/SseEmitterManagerTest.java index ef0fd60a..288529ac 100644 --- a/src/test/java/com/sillim/recordit/pushalarm/service/SseEmitterManagerTest.java +++ b/src/test/java/com/sillim/recordit/pushalarm/service/SseEmitterManagerTest.java @@ -4,7 +4,6 @@ import com.sillim.recordit.pushalarm.dto.AlarmType; import com.sillim.recordit.pushalarm.dto.PushMessage; -import java.io.IOException; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -14,7 +13,7 @@ class SseEmitterManagerTest { @Test @DisplayName("sseEmitter로 client에게 message를 보낼 수 있다.") - void sendToClient() throws IOException { + void sendToClient() { long memberId = 1L; sseEmitterManager.subscribe(memberId); @@ -27,7 +26,7 @@ void sendToClient() throws IOException { @Test @DisplayName("subscribe한 client가 없으면 message를 보낼 수 없다.") - void cantSendToClientIfNotExistsClientSubscribeSseEmitter() throws IOException { + void cantSendToClientIfNotExistsClientSubscribeSseEmitter() { long memberId = 1L; boolean result =