Skip to content

Commit

Permalink
Merge pull request #212 from kookmin-sw/#198-on/offline
Browse files Browse the repository at this point in the history
#198 on/offline
  • Loading branch information
hyeesw authored May 10, 2024
2 parents e9db52b + 5af9e0c commit 881a2f5
Show file tree
Hide file tree
Showing 8 changed files with 87 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import org.springframework.http.ResponseEntity;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.Payload;
import org.springframework.messaging.simp.SimpMessageHeaderAccessor;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
Expand All @@ -35,10 +36,12 @@ public class CafeController {
/pub/cafe/update로 메시지 발행
*/
@MessageMapping("/cafe/update") // pub/cafe/update
public void publishCafeUpdate(@AuthenticationPrincipal User user, @Payload CafeDto dto)
public void publishCafeUpdate(@AuthenticationPrincipal User user, @Payload CafeDto dto,
SimpMessageHeaderAccessor headerAccessor)
throws JsonProcessingException {
String sessionId = headerAccessor.getSessionId(); // 웹소켓 session id
log.info("Message Catch!!");
cafePublisher.updateCafeChoice(dto);
cafePublisher.updateCafeChoice(sessionId, dto);
}

// (지도 페이지) 특정 카페에 속한 모든 유저들을 redis에서 찾아 각 유저 정보를 조회해 프론트로 보낸다.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import com.coffee.backend.domain.cafe.dto.CafeSubDto;
import com.coffee.backend.domain.cafe.dto.CafeUserDto;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
import org.springframework.messaging.simp.SimpMessageSendingOperations;
import org.springframework.stereotype.Service;
Expand All @@ -15,23 +14,24 @@ public class CafePublisher {
private final CafeService cafeService;
private final SimpMessageSendingOperations sendingOperations;

public void updateCafeChoice(CafeDto dto) throws JsonProcessingException, IllegalArgumentException {
public void updateCafeChoice(String sessionId, CafeDto dto)
throws JsonProcessingException, IllegalArgumentException {
String type = dto.getType();
Long userId = dto.getUserId();
String cafeId = dto.getCafeId();

switch (type) {
case "add":
cafeService.addCafeChoice(cafeId, userId);
cafeService.addCafeChoice(cafeId, userId, sessionId);
break;
case "delete":
cafeService.deleteCafeChoice(cafeId, userId);
cafeService.deleteCafeChoice(cafeId, userId, sessionId);
break;
default:
throw new IllegalArgumentException(
"updateCafeChoice : request type 형식을 (add/delete) 중 하나로 작성해주세요. 입력 type: '" + type + "'");
}
String cafeDtoJson = new ObjectMapper().writeValueAsString(dto);

// 해당 user의 전체 정보를 조회
CafeUserDto cafeUserDto = cafeService.getUserInfoFromDB(userId);
CafeSubDto cafeSubDto = CafeSubDto.builder().type(type).userId(userId).cafeId(cafeId).cafeUserDto(cafeUserDto)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
package com.coffee.backend.domain.cafe.service;

import com.coffee.backend.domain.cafe.dto.CafeUserDto;
import com.coffee.backend.domain.user.entity.User;
import com.coffee.backend.domain.user.repository.UserRepository;
import com.coffee.backend.domain.user.service.UserService;
import com.coffee.backend.exception.CustomException;
import com.coffee.backend.exception.ErrorCode;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
Expand All @@ -19,9 +23,10 @@
public class CafeService {
private final RedisTemplate<String, Object> redisTemplate;
private final UserService userService;
private final UserRepository userRepository;

//redis에 add 하는 메소드
public void addCafeChoice(String cafeId, Long userId) {
public void addCafeChoice(String cafeId, Long userId, String sessionId) {
System.out.println("addCafeChoice() 진입");
/*
Redis에 아래 형식으로 저장됨
Expand All @@ -30,12 +35,28 @@ public void addCafeChoice(String cafeId, Long userId) {
value = set(user1, user2, user3)
*/
String cafeChoiceKey = "cafe:" + cafeId;

// 이미 해당 카페에 존재하는 사용자인지 확인
String userIdStr = String.valueOf(userId); // Long 타입을 String으로 변환
redisTemplate.opsForSet().add(cafeChoiceKey, userIdStr); // 카페 ID에 해당하는 세트에 사용자 ID 추가
Boolean isMember = redisTemplate.opsForSet().isMember(cafeChoiceKey, userIdStr);
if (Boolean.TRUE.equals(isMember)) {
throw new IllegalArgumentException(
"Add Exception: " + "'" + userId + "'" + " 는 " + cafeId + "' 카페에 이미 속해 있습니다.");
}

// 카페 ID에 해당하는 세트에 사용자 추가
redisTemplate.opsForSet().add(cafeChoiceKey, userIdStr);

// UserDB에 cafeId, sessionId 저장
userRepository.findByUserId(userId).ifPresent(user -> {
user.setCafeId(cafeId);
user.setSessionId(sessionId);
userRepository.save(user);
});
}

//redis에서 delete 하는 메소드
public void deleteCafeChoice(String cafeId, Long userId) {
// redis 카페선택 삭제, UserDB에 cafeId, sessionId null 로 초기화
public void deleteCafeChoice(String cafeId, Long userId, String sessionId) {
System.out.println("deleteCafeChoice() 진입");
final String cafeChoiceKey = "cafe:" + cafeId;

Expand All @@ -47,9 +68,14 @@ public void deleteCafeChoice(String cafeId, Long userId) {
} else {
throw new IllegalArgumentException("User ID '" + userId + "' 는 '" + cafeId + "' 카페에 속해 있지 않습니다.");
}
// 해당 User cafeId, sessionId null 로 초기화
userRepository.findByLoginId(loginId).ifPresent(user -> {
user.setCafeId(null);
user.setSessionId(null);
userRepository.save(user);
});
}


public List<CafeUserDto> getUserProfilesFromRedisAndDB(String cafeId) {
// cafeId 를 가진 유저를 redis 에서 싹 조회
Set<Object> userSet = getUserListFromRedis(cafeId);
Expand All @@ -70,4 +96,13 @@ public Set<Object> getUserListFromRedis(String cafeId) {
public CafeUserDto getUserInfoFromDB(Long userId) {
return userService.getCafeUserInfoByLoginId(userId); // userId로 User entity 조회
}

public void clearSessionAndCafeIdBySessionId(String sessionId) {
User user = userRepository.findBySessionId(sessionId).orElseThrow(() -> {
log.info("sessionId = {} 를 갖는 사용자가 존재하지 않습니다.", sessionId);
return new CustomException(ErrorCode.USER_NOT_FOUND);
});
// redis 에서 cafeId 유저 삭제 및 cafeId, sessionId null 로 초기화
deleteCafeChoice(user.getCafeId(), user.getLoginId(), sessionId);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,6 @@ public class User {
private String userUUID;
private String introduction;
private String deviceToken;
private String cafeId;
private String sessionId; //websocket 세션 id
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,6 @@ public interface UserRepository extends JpaRepository<User, Long> {
Optional<User> findByKakaoId(Long kakaoId);

Optional<User> findByUserId(Long userId);

Optional<User> findBySessionId(String sessionId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,17 @@ public UserDto updateUserIntroduction(User user, String introduction) {
return customMapper.toUserDto(userRepository.save(user));
}


public void updateUserSessionId(Long userId, String sessionId) {
User user = userRepository.findByUserId(userId)
.orElseThrow(() -> {
log.info("id = {} 인 사용자가 존재하지 않습니다", userId);
return new CustomException(ErrorCode.USER_NOT_FOUND);
});
user.setSessionId(sessionId);
userRepository.save(user);
}

public UserDto resetCompany(User user) {
user.setCompany(null);
return customMapper.toUserDto(userRepository.save(user));
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,24 @@
package com.coffee.backend.global;

import com.coffee.backend.domain.cafe.service.CafeService;
import lombok.AllArgsConstructor;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.event.EventListener;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.messaging.simp.stomp.StompHeaderAccessor;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;
import org.springframework.web.socket.messaging.SessionDisconnectEvent;

@Configuration
@EnableWebSocket
@EnableWebSocketMessageBroker
@AllArgsConstructor
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
private final CafeService cafeService;

@Override
public void configureMessageBroker(final MessageBrokerRegistry registry) {
registry.enableSimpleBroker("/sub"); // 구독요청
Expand All @@ -23,4 +31,12 @@ public void registerStompEndpoints(final StompEndpointRegistry registry) {
.setAllowedOriginPatterns("*")
.withSockJS();
}
}

// 웹소켓 해제 감지 -> 세션 ID, cafeId 초기화
@EventListener
public void onSessionDisconnect(SessionDisconnectEvent event) {
StompHeaderAccessor headerAccessor = StompHeaderAccessor.wrap(event.getMessage());
String sessionId = headerAccessor.getSessionId();
cafeService.clearSessionAndCafeIdBySessionId(sessionId); // 세션 ID, cafeId null
}
}
5 changes: 5 additions & 0 deletions backend/src/main/resources/db/migration/V3__add_cafeid.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
ALTER TABLE user
ADD COLUMN cafe_id VARCHAR(255);

ALTER TABLE user
ADD COLUMN session_id VARCHAR(255);

0 comments on commit 881a2f5

Please sign in to comment.