Skip to content
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

[BE] 타이머 Websocket에 STOMP 적용 #1068

Merged
merged 2 commits into from
Feb 4, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;

@Configuration
public class SchedulerConfig {

@Bean
@Primary
public ThreadPoolTaskScheduler threadPoolTaskScheduler() {
final ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
scheduler.setPoolSize(100);
Expand Down
40 changes: 28 additions & 12 deletions backend/src/main/java/site/coduo/sync/service/SchedulerService.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import java.time.temporal.ChronoUnit;
import java.util.concurrent.ScheduledFuture;

import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.scheduling.Trigger;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.scheduling.support.PeriodicTrigger;
Expand All @@ -14,9 +15,11 @@
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import site.coduo.timer.domain.Timer;
import site.coduo.timer.domain.TimerStatus;
import site.coduo.timer.repository.TimerEntity;
import site.coduo.timer.repository.TimerRepository;
import site.coduo.timer.service.TimestampRegistry;
import site.coduo.timer.service.dto.TimerResponse;
import site.coduo.websocket.PairRoomWebSocketService;
import site.coduo.websocket.message.EventAndDataMessage;

Expand All @@ -28,6 +31,7 @@ public class SchedulerService {

public static final Duration DELAY_SECOND = Duration.of(1, ChronoUnit.SECONDS);

private final SimpMessagingTemplate messagingTemplate;
private final PairRoomWebSocketService pairRoomWebSocketService;
private final ThreadPoolTaskScheduler taskScheduler;
private final SchedulerRegistry schedulerRegistry;
Expand All @@ -38,7 +42,10 @@ public void start(final String key) {
if (schedulerRegistry.isActive(key)) {
return;
}
pairRoomWebSocketService.sendAllPairRoomSessions(key, new EventAndDataMessage("timer", "start"));
messagingTemplate.convertAndSend(
"/topic/" + key + "/timer/status",
new TimerResponse(TimerStatus.START.getName())
);
if (isInitial(key)) {
final Timer timer = timerRepository.fetchTimerByAccessCode(key)
.toDomain();
Expand All @@ -65,13 +72,16 @@ private void runTimer(final String key, final Timer timer) {
stop(key, timer);
return;
}
if (pairRoomWebSocketService.hasNoConnections(key) && schedulerRegistry.has(key)) {
pauseTimer(key);
return;
}
// todo - STOMP에서 특정 topic을 구독하고 있는 사용자 수를 가져올 방법 생각
// if (pairRoomWebSocketService.hasNoConnections(key) && schedulerRegistry.has(key)) {
// pauseTimer(key);
// return;
// }
Comment on lines +76 to +79
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

같이 회의해봅시다

timer.decreaseRemainingTime(DELAY_SECOND.toMillis());
pairRoomWebSocketService.sendAllPairRoomSessions(key,
new EventAndDataMessage("remaining-time", String.valueOf(timer.getRemainingTime())));
messagingTemplate.convertAndSend(
"/topic/" + key + "/timer",
new TimerResponse(timer.getRemainingTime())
);
}

private void pauseTimer(final String key) {
Expand All @@ -82,11 +92,15 @@ private void pauseTimer(final String key) {

public void pause(final String key) {
pauseTimer(key);
pairRoomWebSocketService.sendAllPairRoomSessions(key, new EventAndDataMessage("timer", "pause"));
messagingTemplate.convertAndSend(
"/topic/" + key + "/timer/status",
new TimerResponse(TimerStatus.PAUSE.getName()));
}

private void stop(final String key, final Timer timer) {
pairRoomWebSocketService.sendAllPairRoomSessions(key, new EventAndDataMessage("timer", "stop"));
messagingTemplate.convertAndSend(
"/topic/" + key + "/timer/status",
new TimerResponse(TimerStatus.PAUSE.getName()));
schedulerRegistry.release(key);
final Timer initalTimer = new Timer(timer.getAccessCode(), timer.getDuration(), timer.getDuration());
timestampRegistry.register(key, initalTimer);
Expand All @@ -99,8 +113,10 @@ public void notifyTimerStatus(final WebSocketSession session, final String pairR
}

public void syncTimerWithDatabase(final String key) {
final Timer timer = timestampRegistry.get(key);
final TimerEntity timerEntity = timerRepository.fetchTimerByAccessCode(key);
timerEntity.updateTimer(timer);
if (timestampRegistry.has(key)) {
final Timer timer = timestampRegistry.get(key);
final TimerEntity timerEntity = timerRepository.fetchTimerByAccessCode(key);
timerEntity.updateTimer(timer);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,12 @@
import site.coduo.timer.controller.docs.TimerDocs;
import site.coduo.timer.service.TimerService;
import site.coduo.timer.service.dto.TimerUpdateRequest;
import site.coduo.websocket.PairRoomWebSocketService;
import site.coduo.websocket.message.EventAndDataMessage;

@Slf4j
@RequiredArgsConstructor
@RestController
public class TimerController implements TimerDocs {

private final PairRoomWebSocketService pairRoomWebSocketService;
private final TimerService timerService;
private final SchedulerService schedulerService;

Expand All @@ -36,7 +33,6 @@ public ResponseEntity<Void> createTimerStart(@PathVariable("accessCode") final S
@PatchMapping("/{accessCode}/timer/stop")
public ResponseEntity<Void> createTimerStop(@PathVariable("accessCode") final String accessCode) {
schedulerService.pause(accessCode);

return ResponseEntity.noContent()
.build();
}
Expand All @@ -47,8 +43,6 @@ public ResponseEntity<Void> updateTimer(
@Valid @RequestBody final TimerUpdateRequest request
) {
timerService.updateTimer(accessCode, request);
pairRoomWebSocketService.sendAllPairRoomSessions(accessCode, new EventAndDataMessage("timer", "update"));

return ResponseEntity.noContent()
.build();
}
Expand Down
15 changes: 15 additions & 0 deletions backend/src/main/java/site/coduo/timer/domain/TimerStatus.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package site.coduo.timer.domain;

import lombok.Getter;
import lombok.RequiredArgsConstructor;

@Getter
@RequiredArgsConstructor
public enum TimerStatus {

START("start"),
PAUSE("pause"),
UPDATE("update");

private final String name;
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package site.coduo.timer.service;

import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

Expand All @@ -8,15 +9,18 @@
import site.coduo.pairroom.repository.PairRoomEntity;
import site.coduo.pairroom.repository.PairRoomRepository;
import site.coduo.timer.domain.Timer;
import site.coduo.timer.domain.TimerStatus;
import site.coduo.timer.repository.TimerEntity;
import site.coduo.timer.repository.TimerRepository;
import site.coduo.timer.service.dto.TimerResponse;
import site.coduo.timer.service.dto.TimerUpdateRequest;

@Transactional(readOnly = true)
@RequiredArgsConstructor
@Service
public class TimerService {

private final SimpMessagingTemplate messagingTemplate;
private final TimerRepository timerRepository;
private final TimestampRegistry timestampRegistry;
private final PairRoomRepository pairRoomRepository;
Expand All @@ -42,5 +46,9 @@ public void updateTimer(final String accessCode, final TimerUpdateRequest update
);
timerEntity.updateTimer(newTimer);
timestampRegistry.register(accessCode, newTimer);
messagingTemplate.convertAndSend(
"/topic/" + accessCode + "/timer/status",
new TimerResponse(TimerStatus.UPDATE.getName())
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package site.coduo.timer.service.dto;

public record TimerResponse(
Object data
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

요건 왜 Object 타입이십니까?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

타이머 상태를 보낼때는 String 타입이고, 타이머 시각을 보낼때는 long 타입이여서 TimerResponse로 한번에 데이터를 전송하려고 Object 타입을 사용해습니당

) {
}
7 changes: 0 additions & 7 deletions backend/src/test/java/site/coduo/config/TestConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Primary;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;

import site.coduo.fake.FakeGithubApiClient;
import site.coduo.fake.FakeGithubOAuthClient;
Expand Down Expand Up @@ -40,10 +39,4 @@ public GithubOAuthClient fakeGithubOAuthClient() {
public GithubApiClient fakeGithubApiClient() {
return new FakeGithubApiClient();
}

@Bean
@Primary
public ThreadPoolTaskScheduler testThreadPoolTaskScheduler() {
return new ThreadPoolTaskScheduler();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;

import site.coduo.pairroom.domain.accesscode.AccessCode;
Expand All @@ -29,8 +30,7 @@ class SchedulerServiceTest {

@Autowired
private PairRoomWebSocketService pairRoomWebSocketService;

@Autowired

private ThreadPoolTaskScheduler taskScheduler;

@Autowired
Expand All @@ -39,6 +39,7 @@ class SchedulerServiceTest {
@Autowired
private TimestampRegistry timestampRegistry;

private SimpMessagingTemplate messagingTemplate;
private TimerRepository timerRepository;
private SchedulerService schedulerService;

Expand All @@ -48,6 +49,7 @@ void setUp() {
pairRoomWebSocketService = mock(PairRoomWebSocketService.class);

schedulerService = new SchedulerService(
messagingTemplate,
pairRoomWebSocketService,
taskScheduler,
schedulerRegistry,
Expand Down
Loading