Skip to content

Commit a938e40

Browse files
authored
hotfix : 제출 제대로 안 되는 부분 해결 (제출 씹힘 현상) (#68)
* refactor : 쓰레드 풀 추가 * refactor : 예외처리 고도화 * refactor : Redis Stream Cleanup * feat : Discord 알림 * fix : 비동기 메서드에서 시큐리티 컨텍스트 전파 되지 않는 현상 수정 * fix : CI 환경 변수 추가 * refactor : 로깅 처리 변경 * refactor : 예외 처리 변경 * refactor : 예외처리 고도화 # Conflicts: # src/main/java/org/ezcode/codetest/common/base/exception/GlobalExceptionHandler.java * fix : 비동기 메서드에서 시큐리티 컨텍스트 전파 되지 않는 현상 수정 * refactor : 토끼 리뷰 반영 * refactor : 토끼 리뷰 반영 * hotfix : 제출 안 되는 부분 해결
1 parent c0597cb commit a938e40

File tree

5 files changed

+30
-8
lines changed

5 files changed

+30
-8
lines changed

src/main/java/org/ezcode/codetest/application/submission/service/SubmissionService.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,8 @@ public SseEmitter enqueueCodeSubmission(Long problemId, CodeSubmitRequest reques
7777
emitterStore.remove(emitterKey);
7878
});
7979

80-
emitterStore.save(emitterKey, emitter);
80+
log.info("[SSE 저장] emitterKey: {}", emitterKey);
81+
emitterStore.save(emitterKey, emitter);
8182

8283
queueProducer.enqueue(
8384
new SubmissionMessage(emitterKey, problemId, request.languageId(), authUser.getId(), request.sourceCode())
@@ -90,6 +91,7 @@ public SseEmitter enqueueCodeSubmission(Long problemId, CodeSubmitRequest reques
9091
public void submitCodeStream(SubmissionMessage msg) {
9192
try {
9293
log.info("[Submission RUN] Thread = {}", Thread.currentThread().getName());
94+
log.info("[큐 수신] SubmissionMessage.emitterKey: {}", msg.emitterKey());
9395
User user = userDomainService.getUserById(msg.userId());
9496
Language language = languageDomainService.getLanguage(msg.languageId());
9597
ProblemInfo problemInfo = problemDomainService.getProblemInfo(msg.problemId());
@@ -126,7 +128,9 @@ public void submitCodeStream(SubmissionMessage msg) {
126128
}
127129

128130
if (!context.latch().await(60, TimeUnit.SECONDS)) {
129-
throw new SubmissionException(SubmissionExceptionCode.TESTCASE_TIMEOUT);
131+
emitter.completeWithError(new SubmissionException(SubmissionExceptionCode.TESTCASE_TIMEOUT));
132+
emitterStore.remove(msg.emitterKey());
133+
return;
130134
}
131135

132136
emitter.send(SseEmitter.event()

src/main/java/org/ezcode/codetest/infrastructure/event/config/RedisStreamConfig.java

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import org.ezcode.codetest.infrastructure.event.listener.RedisJudgeQueueConsumer;
88
import org.springframework.context.annotation.Bean;
99
import org.springframework.context.annotation.Configuration;
10+
import org.springframework.data.redis.connection.RedisConnection;
1011
import org.springframework.data.redis.connection.RedisConnectionFactory;
1112
import org.springframework.data.redis.connection.stream.MapRecord;
1213
import org.springframework.data.redis.connection.stream.ReadOffset;
@@ -43,6 +44,20 @@ public void initConsumerGroup() {
4344
));
4445
}
4546

47+
try {
48+
log.info("Redis Consumer Group의 기존 컨슈머 삭제 시도");
49+
redisTemplate.execute((RedisConnection connection) -> {
50+
connection.xGroupDelConsumer(
51+
"judge-queue".getBytes(),
52+
"judge-group",
53+
"consumer-1"
54+
);
55+
return null;
56+
});
57+
} catch (Exception e) {
58+
log.warn("DELCONSUMER 중 오류 발생: {}", e.getMessage());
59+
}
60+
4661
redisTemplate.opsForStream().createGroup("judge-queue", ReadOffset.latest(), "judge-group");
4762

4863
log.info("Redis Stream 'judge-queue'에 대한 Consumer Group 'judge-group'을 생성했습니다.");
@@ -57,7 +72,7 @@ public void initConsumerGroup() {
5772
}
5873
}
5974

60-
@Bean
75+
@Bean(destroyMethod = "stop")
6176
public StreamMessageListenerContainer<String, MapRecord<String, String, String>> streamMessageListenerContainer(
6277
RedisConnectionFactory factory,
6378
RedisJudgeQueueConsumer consumer
@@ -68,7 +83,7 @@ public StreamMessageListenerContainer<String, MapRecord<String, String, String>>
6883
.StreamMessageListenerContainerOptions
6984
.builder()
7085
.executor(consumerExecutor)
71-
.pollTimeout(Duration.ofSeconds(1))
86+
.pollTimeout(Duration.ofSeconds(2))
7287
.build();
7388

7489
StreamMessageListenerContainer<String, MapRecord<String, String, String>> container =

src/main/java/org/ezcode/codetest/infrastructure/event/listener/RedisJudgeQueueConsumer.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,14 @@ public void onMessage(MapRecord<String, String, String> message) {
3535
);
3636

3737
try {
38+
log.info("[컨슈머 수신] {}", msg.emitterKey());
3839
submissionService.submitCodeStream(msg);
39-
redisTemplate.opsForStream().acknowledge("judge-group", message);
4040
} catch (Exception e) {
4141
log.error("채점 메시지 처리 실패: {}", message.getId(), e);
4242
throw new SubmissionException(SubmissionExceptionCode.REDIS_SERVER_ERROR);
43+
} finally {
44+
log.info("[컨슈머 ACK] messageId={}", message.getId());
45+
redisTemplate.opsForStream().acknowledge("judge-group", message);
4346
}
4447
}
4548
}

src/main/java/org/ezcode/codetest/infrastructure/event/service/RedisJudgeQueueProducer.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,17 @@
88
import org.springframework.stereotype.Component;
99

1010
import lombok.RequiredArgsConstructor;
11+
import lombok.extern.slf4j.Slf4j;
1112

13+
@Slf4j
1214
@Component
1315
@RequiredArgsConstructor
1416
public class RedisJudgeQueueProducer implements QueueProducer {
1517

1618
private final RedisTemplate<String, String> redisTemplate;
1719

1820
public void enqueue(SubmissionMessage submissionMessage) {
21+
log.info("[SSE enqueue] emitterKey: {}", submissionMessage.emitterKey());
1922
Map<String, String> map = Map.of(
2023
"emitterKey", submissionMessage.emitterKey(),
2124
"problemId", submissionMessage.problemId().toString(),

src/main/java/org/ezcode/codetest/infrastructure/sse/InMemoryEmitterStore.java

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,6 @@ public class InMemoryEmitterStore implements EmitterStore {
1616
@Override
1717
public void save(String key, SseEmitter emitter) {
1818
emitterMap.put(key, emitter);
19-
emitter.onCompletion(() -> emitterMap.remove(key));
20-
emitter.onTimeout(() -> emitterMap.remove(key));
21-
emitter.onError((e) -> emitterMap.remove(key));
2219
}
2320

2421
@Override

0 commit comments

Comments
 (0)