11package com .back .web7_9_codecrete_be .domain .chats .service ;
22
33import java .security .Principal ;
4+ import java .time .Duration ;
45import java .time .LocalDateTime ;
56
67import org .springframework .data .redis .core .RedisTemplate ;
78import org .springframework .messaging .simp .SimpMessagingTemplate ;
9+ import org .springframework .security .core .Authentication ;
810import org .springframework .stereotype .Service ;
911
1012import com .back .web7_9_codecrete_be .domain .chats .dto .request .ChatMessageRequest ;
1113import com .back .web7_9_codecrete_be .domain .chats .dto .response .ChatMessageResponse ;
1214import com .back .web7_9_codecrete_be .domain .chats .dto .response .ChatUserCache ;
1315import com .back .web7_9_codecrete_be .domain .chats .repository .ChatStreamRepository ;
16+ import com .back .web7_9_codecrete_be .global .security .CustomUserDetail ;
1417import com .back .web7_9_codecrete_be .global .websocket .ChatCountBroadcaster ;
18+ import com .back .web7_9_codecrete_be .global .websocket .ServerInstanceId ;
1519
1620import lombok .RequiredArgsConstructor ;
1721import lombok .extern .slf4j .Slf4j ;
@@ -28,9 +32,29 @@ public class ChatMessageService {
2832 private final RedisTemplate <String , Object > redisTemplate ;
2933 private final ChatCountBroadcaster chatCountBroadcaster ;
3034
31- public void sendMessage (ChatMessageRequest request , Principal principal ) {
35+ /**
36+ * 채팅 메시지 전송 + 세션 TTL 갱신
37+ */
38+ public void handleSend (ChatMessageRequest request , Principal principal ) {
3239
33- String email = principal .getName ();
40+ if (!(principal instanceof Authentication authentication )) {
41+ throw new IllegalStateException ("Unauthenticated WebSocket access" );
42+ }
43+
44+ CustomUserDetail userDetail =
45+ (CustomUserDetail ) authentication .getPrincipal ();
46+
47+ Long userId = userDetail .getUser ().getId ();
48+
49+ extendUserSessionTtl (userId );
50+
51+ sendMessage (request , userDetail .getUsername ());
52+ }
53+
54+ /**
55+ * 실제 메시지 저장 + 브로드캐스트
56+ */
57+ private void sendMessage (ChatMessageRequest request , String email ) {
3458
3559 ChatUserCache chatUser = chatUserCacheService .getChatUser (email );
3660
@@ -42,8 +66,10 @@ public void sendMessage(ChatMessageRequest request, Principal principal) {
4266 LocalDateTime .now ()
4367 );
4468
45- log .info ("[SEND MESSAGE] From User ID: {}, Content: {}" , chatUser .getUserId (), request .getContent ());
69+ log .info ("[SEND MESSAGE] From User ID: {}, Content: {}" ,
70+ chatUser .getUserId (), request .getContent ());
4671
72+ // Redis Stream 저장
4773 chatStreamRepository .save (response );
4874
4975 // WebSocket 브로드캐스트
@@ -53,6 +79,23 @@ public void sendMessage(ChatMessageRequest request, Principal principal) {
5379 );
5480 }
5581
82+ /**
83+ * 유저 세션 TTL 연장
84+ */
85+ private void extendUserSessionTtl (Long userId ) {
86+
87+ String sessionSetKey =
88+ "chat:server:" + ServerInstanceId .ID + ":user:" + userId + ":sessionIds" ;
89+
90+ redisTemplate .expire (sessionSetKey , Duration .ofHours (2 ));
91+
92+ log .debug ("[CHAT TTL] session TTL extended: userId={}, key={}" , userId , sessionSetKey );
93+ }
94+
95+
96+ /**
97+ * 채팅방 접속자 수 브로드캐스트
98+ */
5699 public void broadcastUserCount (Long concertId ) {
57100
58101 String key = "chat:concert:" + concertId + ":users" ;
0 commit comments