Skip to content

Commit

Permalink
🐞 BugFix/#175 - feat: like 생성 μ‹œ λ™μ‹œμ„± 문제 ν•΄κ²°
Browse files Browse the repository at this point in the history
  • Loading branch information
dongkyeomjang committed Nov 27, 2024
1 parent 321ebea commit 2cb2210
Show file tree
Hide file tree
Showing 8 changed files with 138 additions and 57 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,7 @@ public ResponseDto<Void> likeBoard(
@AccountID UUID accountId,
@PathVariable Long id
) {
if (createOrDeleteLikeUseCase.execute(accountId, id)) {
return ResponseDto.created(null);
} else {
return ResponseDto.ok(null);
}
createOrDeleteLikeUseCase.execute(accountId, id);
return ResponseDto.ok(null);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package com.daon.onjung.suggestion.application.controller.consumer;

import com.daon.onjung.account.domain.User;
import com.daon.onjung.account.repository.mysql.UserRepository;
import com.daon.onjung.core.exception.error.ErrorCode;
import com.daon.onjung.core.exception.type.CommonException;
import com.daon.onjung.suggestion.application.dto.request.LikeMessage;
import com.daon.onjung.suggestion.domain.Board;
import com.daon.onjung.suggestion.domain.Like;
import com.daon.onjung.suggestion.domain.service.BoardService;
import com.daon.onjung.suggestion.domain.service.LikeService;
import com.daon.onjung.suggestion.repository.mysql.BoardRepository;
import com.daon.onjung.suggestion.repository.mysql.LikeRepository;
import lombok.RequiredArgsConstructor;
import org.hibernate.dialect.lock.OptimisticEntityLockException;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@RequiredArgsConstructor
public class LikeV1Consumer {

private final LikeRepository likeRepository;
private final BoardRepository boardRepository;
private final UserRepository userRepository;

private final LikeService likeService;
private final BoardService boardService;

@Transactional
@RabbitListener(queues = "like-queue")
public void processLikeMessage(LikeMessage likeMessage) {
try {

// κ²Œμ‹œκΈ€ 쑰회
Board board = boardRepository.findById(likeMessage.boardId())
.orElseThrow(() -> new CommonException(ErrorCode.NOT_FOUND_RESOURCE));

// μœ μ € 쑰회
User user = userRepository.findById(likeMessage.userId())
.orElseThrow(() -> new CommonException(ErrorCode.NOT_FOUND_RESOURCE));

// μ’‹μ•„μš”κ°€ μ‘΄μž¬ν•˜λŠ”μ§€ 확인
Like like = likeRepository.findByBoardAndUser(board, user)
.orElse(null);

if (like != null) {

// μ’‹μ•„μš”κ°€ 이미 μ‘΄μž¬ν•˜λ©΄ μ‚­μ œ
likeRepository.delete(like);
// κ²Œμ‹œκΈ€ μ’‹μ•„μš” 수 κ°μ†Œ
board = boardService.subtractLikeCount(board);
boardRepository.save(board);
} else {

// μ’‹μ•„μš”κ°€ μ‘΄μž¬ν•˜μ§€ μ•ŠμœΌλ©΄ 생성
likeRepository.save(likeService.createLike(user, board));

// κ²Œμ‹œκΈ€ μ’‹μ•„μš” 수 증가
board = boardService.addLikeCount(board);
boardRepository.save(board);
}
} catch (OptimisticEntityLockException e) {
throw new CommonException(ErrorCode.OPTIMISTIC_EXCEPTION);
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.daon.onjung.suggestion.application.controller.producer;

import com.daon.onjung.suggestion.application.dto.request.LikeMessage;
import com.daon.onjung.suggestion.application.usecase.SendLikeRequestUseCase;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

@Service
@RequiredArgsConstructor
public class LikeV1Producer {

private final SendLikeRequestUseCase sendLikeRequestUseCase;

public void sendLike (LikeMessage likeMessage) {
sendLikeRequestUseCase.execute(likeMessage);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.daon.onjung.suggestion.application.dto.request;

import lombok.Builder;

import java.util.UUID;

@Builder
public record LikeMessage(
Long boardId,
UUID userId
) {
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,8 @@
package com.daon.onjung.suggestion.application.service;

import com.daon.onjung.account.domain.User;
import com.daon.onjung.account.repository.mysql.UserRepository;
import com.daon.onjung.core.exception.error.ErrorCode;
import com.daon.onjung.core.exception.type.CommonException;
import com.daon.onjung.suggestion.application.controller.producer.LikeV1Producer;
import com.daon.onjung.suggestion.application.dto.request.LikeMessage;
import com.daon.onjung.suggestion.application.usecase.CreateOrDeleteLikeUseCase;
import com.daon.onjung.suggestion.domain.Board;
import com.daon.onjung.suggestion.domain.Like;
import com.daon.onjung.suggestion.domain.service.BoardService;
import com.daon.onjung.suggestion.domain.service.LikeService;
import com.daon.onjung.suggestion.repository.mysql.BoardRepository;
import com.daon.onjung.suggestion.repository.mysql.LikeRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
Expand All @@ -21,51 +13,16 @@
@RequiredArgsConstructor
public class CreateOrDeleteLikeService implements CreateOrDeleteLikeUseCase {

private final BoardRepository boardRepository;
private final UserRepository userRepository;
private final LikeRepository likeRepository;

private final BoardService boardService;
private final LikeService likeService;

private final LikeV1Producer likeProducer;

@Override
@Transactional
public Boolean execute(UUID accountId, Long boardId) {

// μœ μ € 쑰회
User user = userRepository.findById(accountId)
.orElseThrow(() -> new CommonException(ErrorCode.NOT_FOUND_RESOURCE));

// κ²Œμ‹œκΈ€ 쑰회
Board board = boardRepository.findById(boardId)
.orElseThrow(() -> new CommonException(ErrorCode.NOT_FOUND_RESOURCE));

// μ’‹μ•„μš” μ—¬λΆ€ 확인
Like like = likeRepository.findByBoardAndUser(board, user)
.orElse(null);

// μ’‹μ•„μš” 생성 λ˜λŠ” μ‚­μ œ
if (like != null) {

// μ’‹μ•„μš”κ°€ 이미 μ‘΄μž¬ν•˜λ©΄ μ‚­μ œ
likeRepository.delete(like);

// κ²Œμ‹œκΈ€ μ’‹μ•„μš” 수 κ°μ†Œ
board = boardService.subtractLikeCount(board);
boardRepository.save(board);

return false;
} else {

// μ’‹μ•„μš”κ°€ μ‘΄μž¬ν•˜μ§€ μ•ŠμœΌλ©΄ 생성
likeRepository.save(likeService.createLike(user,board));
public void execute(UUID accountId, Long boardId) {

// κ²Œμ‹œκΈ€ μ’‹μ•„μš” 수 증가
board = boardService.addLikeCount(board);
boardRepository.save(board);
likeProducer.sendLike(LikeMessage.builder()
.boardId(boardId)
.userId(accountId)
.build());

return true;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.daon.onjung.suggestion.application.service;

import com.daon.onjung.suggestion.application.dto.request.LikeMessage;
import com.daon.onjung.suggestion.application.usecase.SendLikeRequestUseCase;
import lombok.RequiredArgsConstructor;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.stereotype.Service;

@Service
@RequiredArgsConstructor
public class SendLikeRequestService implements SendLikeRequestUseCase {

private final RabbitTemplate rabbitTemplate;

@Override
public void execute(LikeMessage likeMessage) {
rabbitTemplate.convertAndSend("like-queue", likeMessage);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@
@UseCase
public interface CreateOrDeleteLikeUseCase {

Boolean execute(UUID accountId, Long boardId);
void execute(UUID accountId, Long boardId);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.daon.onjung.suggestion.application.usecase;

import com.daon.onjung.core.annotation.bean.UseCase;
import com.daon.onjung.suggestion.application.dto.request.LikeMessage;

@UseCase
public interface SendLikeRequestUseCase {
void execute(LikeMessage likeMessage);
}

0 comments on commit 2cb2210

Please sign in to comment.