Skip to content

Commit 15bb20c

Browse files
authored
✨ feat: SSE 하트비트 추가 (#164)
* ✨ feat: SSE 하트비트 추가 * chore: Java 스타일 수정 * ♻️ refactor: SSE 하트비트 주기 30초로 변경 * chore: Java 스타일 수정 * ♻️ refactor: SSE 하트비트 주기 60초로 변경 * chore: Java 스타일 수정 --------- Co-authored-by: github-actions <>
1 parent 7bc737f commit 15bb20c

File tree

3 files changed

+22
-8
lines changed

3 files changed

+22
-8
lines changed

backend/src/main/java/io/f1/backend/domain/game/app/GameService.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ public class GameService {
6464
private final RoomRepository roomRepository;
6565
private final ApplicationEventPublisher eventPublisher;
6666

67-
@DistributedLock(prefix = "room", key = "#roomId", waitTime = 0)
67+
@DistributedLock(prefix = "room", key = "#roomId")
6868
public void gameStart(Long roomId, UserPrincipal principal) {
6969

7070
String destination = getDestination(roomId);

backend/src/main/java/io/f1/backend/domain/game/sse/app/SseService.java

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,28 +9,30 @@
99
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
1010

1111
import java.io.IOException;
12+
import java.util.concurrent.Executors;
13+
import java.util.concurrent.ScheduledExecutorService;
14+
import java.util.concurrent.TimeUnit;
1215

1316
@Service
1417
@RequiredArgsConstructor
1518
public class SseService {
1619

1720
private final SseEmitterRepository emitterRepository;
21+
private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
1822

1923
public SseEmitter subscribe() {
2024
SseEmitter emitter = new SseEmitter(1_800_000L);
2125
emitterRepository.save(emitter);
2226

2327
try {
24-
// emitter 정상 전송확인 메시지
2528
emitter.send(SseEmitter.event().name("connect").data("connected"));
29+
startHeartBeat(emitter);
2630
} catch (IOException e) {
27-
// emitter send() 호출 시 예외 처리
28-
emitterRepository.remove(emitter);
31+
emitter.completeWithError(e);
2932
}
3033
return emitter;
3134
}
3235

33-
// 로비로 SSE 메시지를 쏘기위한 메서드
3436
public <T> void notifyLobbyUpdate(LobbySseEvent<T> event) {
3537
for (SseEmitter emitter : emitterRepository.getAll()) {
3638
try {
@@ -40,4 +42,18 @@ public <T> void notifyLobbyUpdate(LobbySseEvent<T> event) {
4042
}
4143
}
4244
}
45+
46+
private void startHeartBeat(SseEmitter emitter) {
47+
scheduler.scheduleAtFixedRate(
48+
() -> {
49+
try {
50+
emitter.send(SseEmitter.event().name("heartbeat").data("sse-alive"));
51+
} catch (IOException e) {
52+
emitterRepository.remove(emitter);
53+
}
54+
},
55+
5,
56+
60,
57+
TimeUnit.SECONDS);
58+
}
4359
}

backend/src/main/java/io/f1/backend/domain/game/sse/store/SseEmitterRepository.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,18 +13,16 @@ public class SseEmitterRepository {
1313

1414
public void save(SseEmitter emitter) {
1515
emitters.add(emitter);
16-
// 연결종료 객체정리
16+
1717
emitter.onCompletion(() -> emitters.remove(emitter));
1818
emitter.onTimeout(() -> emitters.remove(emitter));
1919
emitter.onError(error -> emitters.remove(emitter));
2020
}
2121

22-
// 연결 종료 객체 정리
2322
public void remove(SseEmitter emitter) {
2423
emitters.remove(emitter);
2524
}
2625

27-
// 브로드캐스팅
2826
public List<SseEmitter> getAll() {
2927
return emitters;
3028
}

0 commit comments

Comments
 (0)