diff --git a/monicar-control-center/src/main/java/org/controlcenter/alarm/application/AlarmService.java b/monicar-control-center/src/main/java/org/controlcenter/alarm/application/AlarmService.java index cf6bd6e..cf78b95 100644 --- a/monicar-control-center/src/main/java/org/controlcenter/alarm/application/AlarmService.java +++ b/monicar-control-center/src/main/java/org/controlcenter/alarm/application/AlarmService.java @@ -36,6 +36,10 @@ public class AlarmService { private final VehicleRepository vehicleRepository; private final ManagerRepository managerRepository; + public Map getSseEmitters() { + return sseEmitters; + } + /** * 특정 userId가 SSE 구독을 시작할 때 호출. */ diff --git a/monicar-control-center/src/main/java/org/controlcenter/alarm/infrastructure/jpa/AlarmJpaRepository.java b/monicar-control-center/src/main/java/org/controlcenter/alarm/infrastructure/jpa/AlarmJpaRepository.java index 69aac6f..acabfc2 100644 --- a/monicar-control-center/src/main/java/org/controlcenter/alarm/infrastructure/jpa/AlarmJpaRepository.java +++ b/monicar-control-center/src/main/java/org/controlcenter/alarm/infrastructure/jpa/AlarmJpaRepository.java @@ -1,6 +1,5 @@ package org.controlcenter.alarm.infrastructure.jpa; -import java.util.List; import java.util.Optional; import org.controlcenter.alarm.domain.AlarmInfo; @@ -35,6 +34,7 @@ Page findAlarmListByStatus(@Param("status") AlarmStatus status, SUM(CASE WHEN a.status = 'COMPLETED' THEN 1 ELSE 0 END) ) FROM alarm a + WHERE a.isChecked = FALSE """) AlarmStatusStats findStatusCounts(); } diff --git a/monicar-control-center/src/main/java/org/controlcenter/common/scheduler/SseHeartbeatScheduler.java b/monicar-control-center/src/main/java/org/controlcenter/common/scheduler/SseHeartbeatScheduler.java new file mode 100644 index 0000000..b938385 --- /dev/null +++ b/monicar-control-center/src/main/java/org/controlcenter/common/scheduler/SseHeartbeatScheduler.java @@ -0,0 +1,32 @@ +package org.controlcenter.common.scheduler; + +import java.io.IOException; + +import lombok.RequiredArgsConstructor; + +import org.controlcenter.alarm.application.AlarmService; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; +import org.springframework.web.servlet.mvc.method.annotation.SseEmitter; + +@Component +@RequiredArgsConstructor +public class SseHeartbeatScheduler { + private final AlarmService alarmService; + + @Scheduled(fixedRate = 15000) + public void sendHeartbeat() { + var emitters = alarmService.getSseEmitters(); + emitters.forEach((userId, emitter) -> { + try { + emitter.send(SseEmitter.event() + .name("ping") + .data("ping")); + } catch (IOException e) { + emitter.complete(); + emitters.remove(userId); + } + }); + } +} +