Skip to content

Commit

Permalink
Merge pull request #182 from 100-hours-a-week/dev
Browse files Browse the repository at this point in the history
v0.1.1 릴리즈
  • Loading branch information
JiHongKim98 authored Sep 4, 2024
2 parents 78942fd + 2bffd89 commit 3d2f6ac
Show file tree
Hide file tree
Showing 17 changed files with 189 additions and 57 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/backend-dev-cd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ jobs:
- name: 도커 허브 리포지토리에서 최신 이미지 가져오기
run: |
sudo docker login --username ${{ secrets.DEV_DOCKER_HUB_USERNAME }} --password ${{ secrets.DEV_DOCKER_HUB_ACCESS_TOKEN }}
sudo docker pull ${{ secrets.DEV_DOCKER_HUB_REPOSITORY }}:${{ secrets.IMAGE_TAG }}
sudo docker pull ${{ secrets.DEV_DOCKER_HUB_REPOSITORY }}:${{ secrets.DEV_IMAGE_TAG }}
- name: blue green 배포
run: |
Expand Down
1 change: 1 addition & 0 deletions docker/init.js
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
db = db.getSiblingDB('dao-local-db');
db.createCollection('chat_message');
db.createCollection('chat_user');
17 changes: 10 additions & 7 deletions src/main/java/com/example/daobe/auth/application/AuthService.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,13 @@
import com.example.daobe.auth.domain.Token;
import com.example.daobe.auth.domain.repository.TokenRepository;
import com.example.daobe.auth.exception.AuthException;
import com.example.daobe.objet.domain.repository.ObjetRepository;
import com.example.daobe.user.domain.User;
import com.example.daobe.user.domain.event.UserCreateEvent;
import com.example.daobe.user.domain.repository.UserRepository;
import com.example.daobe.user.exception.UserException;
import com.example.daobe.user.exception.UserExceptionType;
import lombok.RequiredArgsConstructor;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;

@Service
Expand All @@ -24,11 +25,11 @@ public class AuthService {
private final TokenExtractor tokenExtractor;
private final UserRepository userRepository;
private final TokenRepository tokenRepository;
private final ObjetRepository objetRepository;
private final ApplicationEventPublisher eventPublisher;

public TokenResponseDto loginOrRegister(String oAuthId) {
User findUser = userRepository.findByKakaoId(oAuthId)
.orElseGet(() -> userRepository.save(generatedUser(oAuthId)));
.orElseGet(() -> saveAndPublishEvent(oAuthId));

Token newToken = Token.builder()
.memberId(findUser.getId())
Expand All @@ -40,10 +41,6 @@ public TokenResponseDto loginOrRegister(String oAuthId) {
return TokenResponseDto.of(accessToken, refreshToken);
}

private User generatedUser(String oAuthId) {
return User.builder().kakaoId(oAuthId).build();
}

public TokenResponseDto reissueTokenPair(String currentToken) {
String tokenId = tokenExtractor.extractRefreshToken(currentToken);
Token findToken = tokenRepository.findByTokenId(tokenId)
Expand Down Expand Up @@ -89,4 +86,10 @@ public void withdraw(Long userId, String currentToken, WithdrawRequestDto reques
findUser.withdrawWithAddReason(request.reasonTypeList(), request.detail());
userRepository.save(findUser);
}

private User saveAndPublishEvent(String oAuthId) {
User newUser = userRepository.save(User.builder().kakaoId(oAuthId).build());
eventPublisher.publishEvent(UserCreateEvent.of(newUser));
return newUser;
}
}
41 changes: 30 additions & 11 deletions src/main/java/com/example/daobe/chat/application/ChatService.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,21 @@
import com.example.daobe.chat.application.dto.ChatRoomTokenDto;
import com.example.daobe.chat.domain.ChatMessage;
import com.example.daobe.chat.domain.ChatRoom;
import com.example.daobe.chat.domain.ChatUser;
import com.example.daobe.chat.domain.repository.ChatMessageRepository;
import com.example.daobe.chat.domain.repository.ChatRoomRepository;
import com.example.daobe.chat.domain.repository.ChatUserRepository;
import com.example.daobe.chat.exception.ChatException;
import com.example.daobe.user.application.UserService;
import com.example.daobe.user.application.dto.UserInfoResponseDto;
import java.time.LocalDateTime;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.messaging.simp.SimpMessageHeaderAccessor;
Expand All @@ -40,6 +46,7 @@ public class ChatService {

private final UserService userService;
private final ChatRoomRepository chatRoomRepository;
private final ChatUserRepository chatUserRepository;
private final ChatMessageRepository chatMessageRepository;

@Transactional
Expand Down Expand Up @@ -78,32 +85,44 @@ public EnterAndLeaveMessage createEnterMessageAndSetSessionAttribute(
}

public ChatMessageDto createMessage(ChatMessageDto message, String roomToken) {
Long senderId = message.senderId();
UserInfoResponseDto findUser = userService.getUserInfoWithId(senderId);
ChatUser findUser = chatUserRepository.findByUserId(message.senderId())
.orElseThrow(() -> new RuntimeException("NOT_EXISTS_USER_EXCEPTION"));

ChatMessage chatMessage = ChatMessage.builder()
.type(TALK)
.roomToken(roomToken)
.senderId(findUser.userId())
.sender(findUser.nickname())
.senderProfileUrl(findUser.profileUrl())
.senderId(findUser.getUserId())
.message(message.message())
.build();

// MongoDB 저장
ChatMessage savedChatMessage = chatMessageRepository.save(chatMessage);
return ChatMessageDto.of(savedChatMessage);
return ChatMessageDto.of(savedChatMessage, findUser);
}

public List<ChatMessageDto> getMessagesByRoomToken(String roomToken, boolean isAll) {
List<ChatMessage> chatMessages;
if (isAll) {
return chatMessageRepository.findAllByRoomToken(roomToken).stream()
.map(ChatMessageDto::of)
chatMessages = chatMessageRepository.findAllByRoomToken(roomToken);
} else {
chatMessages = chatMessageRepository.findAllByRoomTokenOrderByCreatedAtDesc(roomToken)
.stream()
.limit(RECENT_MESSAGES_COUNT)
.toList();
}
return chatMessageRepository.findAllByRoomTokenOrderByCreatedAtDesc(roomToken).stream()
.limit(RECENT_MESSAGES_COUNT)
.map(ChatMessageDto::of)

// TODO: Redis 활용한 캐싱 처리 필요
Set<Long> userIds = chatMessages.stream()
.map(ChatMessage::getSenderId)
.collect(Collectors.toSet());
List<ChatUser> chatUsers = chatUserRepository.findAllByUserIdIn(userIds);
Map<Long, ChatUser> userInfos = chatUsers.stream()
.collect(Collectors.toMap(ChatUser::getUserId, Function.identity()));
return chatMessages.stream()
.map(chatMessage -> {
ChatUser chatUser = userInfos.get(chatMessage.getSenderId());
return ChatMessageDto.of(chatMessage, chatUser);
})
.sorted(Comparator.comparing(ChatMessageDto::createdAt))
.toList();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.example.daobe.chat.application.dto;

import com.example.daobe.chat.domain.ChatMessage;
import com.example.daobe.chat.domain.ChatUser;
import java.time.LocalDateTime;

public record ChatMessageDto(
Expand All @@ -13,14 +14,14 @@ public record ChatMessageDto(
String message,
LocalDateTime createdAt
) {
public static ChatMessageDto of(ChatMessage message) {
public static ChatMessageDto of(ChatMessage message, ChatUser sender) {
return new ChatMessageDto(
message.getId(),
message.getType(),
message.getRoomToken(),
message.getSenderId(),
message.getSender(),
message.getSenderProfileUrl(),
sender.getNickname(),
sender.getProfileUrl(),
message.getMessage(),
message.getCreatedAt()
);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package com.example.daobe.chat.application.event;

import com.example.daobe.chat.domain.ChatUser;
import com.example.daobe.chat.domain.repository.ChatUserRepository;
import com.example.daobe.user.domain.event.UserCreateEvent;
import com.example.daobe.user.domain.event.UserUpdateEvent;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;

@Slf4j
@Component
@RequiredArgsConstructor
public class ChatUserEventListener {

private final ChatUserRepository chatUserRepository;

@EventListener
public void handleUserCreated(UserCreateEvent event) {
ChatUser chatUser = ChatUser.builder()
.userId(event.userId())
.nickname(event.nickname())
.profileUrl(event.profileUrl())
.build();
chatUserRepository.save(chatUser);
}

@EventListener
public void handleUserUpdated(UserUpdateEvent event) {
ChatUser findUser = chatUserRepository.findByUserId(event.userId())
.orElseThrow(() -> new RuntimeException("NOT_EXISTS_USER_EXCEPTION"));
findUser.updateUserInfo(event.nickname(), event.profileUrl());
chatUserRepository.save(findUser);
}
}
11 changes: 1 addition & 10 deletions src/main/java/com/example/daobe/chat/domain/ChatMessage.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,24 +34,15 @@ public class ChatMessage {
@Field("sender_id")
private Long senderId;

@Field("sender")
private String sender;

@Field("sender_profile_url")
private String senderProfileUrl;

@Field("created_at")
@CreatedDate
private LocalDateTime createdAt;

@Builder
public ChatMessage(String roomToken, MessageType type, String message, Long senderId, String sender,
String senderProfileUrl) {
public ChatMessage(String roomToken, MessageType type, String message, Long senderId) {
this.roomToken = roomToken;
this.type = type.name();
this.message = message;
this.senderId = senderId;
this.sender = sender;
this.senderProfileUrl = senderProfileUrl;
}
}
45 changes: 45 additions & 0 deletions src/main/java/com/example/daobe/chat/domain/ChatUser.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package com.example.daobe.chat.domain;

import jakarta.persistence.Id;
import lombok.AccessLevel;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.springframework.data.mongodb.core.index.Indexed;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.data.mongodb.core.mapping.Field;

@Getter
@Document(collection = "chat_user")
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class ChatUser {

@Id
private String id;

@Indexed(unique = true)
@Field("user_id")
private Long userId;

@Field("nickname")
private String nickname;

@Field("profile_url")
private String profileUrl;

@Builder
public ChatUser(Long userId, String nickname, String profileUrl) {
this.userId = userId;
this.nickname = nickname;
this.profileUrl = profileUrl;
}

public void updateUserInfo(String nickname, String profileUrl) {
if (nickname != null) {
this.nickname = nickname;
}
if (profileUrl != null) {
this.profileUrl = profileUrl;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.example.daobe.chat.domain.repository;

import com.example.daobe.chat.domain.ChatUser;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import org.springframework.data.mongodb.repository.MongoRepository;

public interface ChatUserRepository extends MongoRepository<ChatUser, String> {

Optional<ChatUser> findByUserId(Long userId);

List<ChatUser> findAllByUserIdIn(Set<Long> userIds);
}
22 changes: 2 additions & 20 deletions src/main/java/com/example/daobe/common/config/RedisConfig.java
Original file line number Diff line number Diff line change
@@ -1,38 +1,20 @@
package com.example.daobe.common.config;

import com.example.daobe.auth.domain.Token;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.repository.configuration.EnableRedisRepositories;

@Configuration
@EnableRedisRepositories
public class RedisConfig {

private final String host;
private final int port;

public RedisConfig(
@Value("${spring.data.redis.host}") String host,
@Value("${spring.data.redis.port}") int port
) {
this.host = host;
this.port = port;
}

@Bean
public RedisConnectionFactory redisConnectionFactory() {
return new LettuceConnectionFactory(host, port);
}

@Bean
public RedisTemplate<String, Token> redisTemplate() {
public RedisTemplate<String, Token> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Token> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactory());
redisTemplate.setConnectionFactory(factory);
return redisTemplate;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ public ObjetDetailInfoDto getObjetDetail(Long objetId) {
.name(findObjet.getName())
.userId(findObjet.getUser().getId())
.nickname(findObjet.getUser().getNickname())
.loungeId(findObjet.getLounge().getId())
.objetImage(findObjet.getImageUrl())
.description(findObjet.getExplanation())
.type(findObjet.getType())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
public record ObjetDetailInfoDto(
Long objetId,
Long userId,
Long loungeId,
String name,
String nickname,
String objetImage,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import com.example.daobe.user.domain.User;
import com.example.daobe.user.domain.UserStatus;
import com.example.daobe.user.domain.event.UserPokeEvent;
import com.example.daobe.user.domain.event.UserUpdateEvent;
import com.example.daobe.user.domain.repository.UserPokeRepository;
import com.example.daobe.user.domain.repository.UserRepository;
import com.example.daobe.user.exception.UserException;
Expand Down Expand Up @@ -49,13 +50,14 @@ public void checkValidateByNickname(String nickname) {
}

@Transactional
public UpdateProfileResponseDto updateNickname(Long userId, UpdateProfileRequestDto request) {
public UpdateProfileResponseDto updateProfile(Long userId, UpdateProfileRequestDto request) {
User findUser = userRepository.findById(userId)
.orElseThrow(() -> new UserException(NOT_EXIST_USER));

findUser.updateUserInfo(request.nickname(), request.profileUrl());

userRepository.save(findUser);
eventPublisher.publishEvent(UserUpdateEvent.of(findUser));

return UpdateProfileResponseDto.of(findUser);
}

Expand All @@ -77,7 +79,7 @@ public void poke(Long userId, UserPokeRequestDto request) {
eventPublisher.publishEvent(userPokeEvent);
}

// FIXME: External Service
// FIXME: EDA 기반으로 수정
public User getUserById(Long userId) {
return userRepository.findById(userId)
.orElseThrow(() -> new UserException(NOT_EXIST_USER));
Expand Down
Loading

0 comments on commit 3d2f6ac

Please sign in to comment.