-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* refactor : SSE 로직 Game에서 분리 * refactor : SSE event publish 로직 bean을 통해 common으로 이동 * refactor : sse disconnect 로직 common으로 이동 * refactor : SseRepository 명 Session 변경 및 infra package로 이동 * Test : SseEventPublisher 테스트 작성 * test : SseAspectTest 구현 * refactor : 상수 함수 내부 변수로 변경 * refactor : final 키워드 추가 및 SseEventBuilder import 추가 * refactor : 메서드 네임 수정 및 Sse 생성 매서드 위치 이동 * refactor : aspect test 수정 * refactor : aspect test method 모킹 * refactor : mockito 버전 문제 해결
- Loading branch information
1 parent
217de8e
commit a1b3e8b
Showing
18 changed files
with
403 additions
and
288 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 1 addition & 1 deletion
2
...ogether/game/annotation/SseSubscribe.java → ...ether/common/annotation/SseSubscribe.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
63 changes: 63 additions & 0 deletions
63
src/main/java/mafia/mafiatogether/common/aspect/SseAspect.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
package mafia.mafiatogether.common.aspect; | ||
|
||
import lombok.RequiredArgsConstructor; | ||
import mafia.mafiatogether.common.annotation.PlayerInfo; | ||
import mafia.mafiatogether.common.exception.AuthException; | ||
import mafia.mafiatogether.common.exception.ExceptionCode; | ||
import mafia.mafiatogether.common.resolver.PlayerInfoDto; | ||
import mafia.mafiatogether.common.domain.SseEmitterSession; | ||
import org.aspectj.lang.ProceedingJoinPoint; | ||
import org.aspectj.lang.annotation.Around; | ||
import org.aspectj.lang.annotation.Aspect; | ||
import org.aspectj.lang.reflect.MethodSignature; | ||
import org.springframework.stereotype.Component; | ||
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter; | ||
|
||
import java.lang.annotation.Annotation; | ||
import java.lang.reflect.Method; | ||
import java.util.Arrays; | ||
|
||
@Aspect | ||
@Component | ||
@RequiredArgsConstructor | ||
public class SseAspect { | ||
|
||
private final SseEmitterSession sseEmitterSession; | ||
|
||
@Around("@annotation(mafia.mafiatogether.common.annotation.SseSubscribe)") | ||
public Object subscribe(final ProceedingJoinPoint joinPoint) throws Throwable { | ||
final MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature(); | ||
final Method method = methodSignature.getMethod(); | ||
|
||
final Annotation[][] parameterAnnotations = method.getParameterAnnotations(); | ||
final Object[] args = joinPoint.getArgs(); | ||
|
||
final String[] codeAndName = new String[2]; | ||
for (int i = 0; i < parameterAnnotations.length; i++) { | ||
if (hasPlayerInfo(parameterAnnotations[i])) { | ||
PlayerInfoDto playerInfoDto = (PlayerInfoDto) args[i]; | ||
codeAndName[0] = playerInfoDto.code(); | ||
codeAndName[1] = playerInfoDto.name(); | ||
break; | ||
} | ||
} | ||
|
||
if (codeAndName[0] == null || codeAndName[1] == null) { | ||
throw new AuthException(ExceptionCode.INVALID_AUTHENTICATION_FORM); | ||
} | ||
|
||
final String code = codeAndName[0]; | ||
final String name = codeAndName[1]; | ||
|
||
final SseEmitter sseEmitter = (SseEmitter) joinPoint.proceed(); | ||
sseEmitterSession.save(code, name, sseEmitter); | ||
sseEmitter.onCompletion(() -> sseEmitterSession.deleteByCodeAndEmitter(code, name)); | ||
sseEmitter.onTimeout(sseEmitter::complete); | ||
|
||
return sseEmitter; | ||
} | ||
|
||
private boolean hasPlayerInfo(final Annotation[] annotations) { | ||
return Arrays.stream(annotations).anyMatch(PlayerInfo.class::isInstance); | ||
} | ||
} |
4 changes: 2 additions & 2 deletions
4
...her/game/domain/SseEmitterRepository.java → ...ther/common/domain/SseEmitterSession.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
65 changes: 65 additions & 0 deletions
65
src/main/java/mafia/mafiatogether/common/infra/SseEventPublisher.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
package mafia.mafiatogether.common.infra; | ||
|
||
import lombok.RequiredArgsConstructor; | ||
import mafia.mafiatogether.common.domain.SseEmitterSession; | ||
import org.springframework.stereotype.Component; | ||
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter; | ||
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter.SseEventBuilder; | ||
|
||
import java.io.IOException; | ||
import java.util.List; | ||
|
||
@Component | ||
@RequiredArgsConstructor | ||
public class SseEventPublisher { | ||
|
||
private static final long HOURS_12 = 43200_000L; | ||
private static final long SECOND_30 = 30_000L; | ||
private final SseEmitterSession sseEmitterSession; | ||
|
||
public void publishEventByCode(final String code, final String eventName, final Object event) { | ||
List<SseEmitter> emitters = sseEmitterSession.findByCode(code); | ||
for (SseEmitter emitter : emitters) { | ||
SseEventBuilder builder = getSseEventBuilder(eventName, event); | ||
publishSseEvent(emitter, builder); | ||
} | ||
} | ||
|
||
private void publishSseEvent(final SseEmitter emitter, final SseEventBuilder eventBuilder) { | ||
try { | ||
emitter.send(eventBuilder); | ||
} catch (IOException e) { | ||
emitter.completeWithError(e); | ||
} | ||
} | ||
|
||
public static SseEventBuilder getSseEventBuilder(final String eventName, final Object event) { | ||
return SseEmitter.event() | ||
.name(eventName) | ||
.data(event) | ||
.reconnectTime(SECOND_30); | ||
} | ||
|
||
public void publishEventByCodeAndName( | ||
final String code, | ||
final String participantName, | ||
final String eventName, | ||
final Object event | ||
) { | ||
SseEmitter sseEmitter = sseEmitterSession.findByCodeAndName(code, participantName); | ||
SseEventBuilder eventBuilder = getSseEventBuilder(eventName, event); | ||
publishSseEvent(sseEmitter, eventBuilder); | ||
} | ||
|
||
public void disconnectSseByCode(final String code) { | ||
sseEmitterSession.deleteByCode(code); | ||
} | ||
|
||
|
||
public static SseEmitter getSseEmitter(final String name, final Object event) throws IOException { | ||
final SseEmitter sseEmitter = new SseEmitter(HOURS_12); | ||
SseEventBuilder sseEventBuilder = SseEventPublisher.getSseEventBuilder(name, event); | ||
sseEmitter.send(sseEventBuilder); | ||
return sseEmitter; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.