Skip to content

Commit 68073e4

Browse files
feat : 채팅 내역 실시간 저장 확인 및 DLQ 구현 시도
1 parent caa3336 commit 68073e4

16 files changed

+273
-25
lines changed

Dockerfile

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
FROM adoptopenjdk/openjdk11 AS builder
2+
3+
COPY gradlew .
4+
COPY gradle gradle
5+
COPY build.gradle .
6+
COPY settings.gradle .
7+
COPY src src
8+
RUN chmod +x ./gradlew #gradlew 실행 권한 부여
9+
RUN ./gradlew bootJar #gradlew를 통해 실행 가능한 jar파일 생성
10+
11+
FROM adoptopenjdk/openjdk11
12+
COPY --from=builder build/libs/*.jar app.jar
13+
ENTRYPOINT ["java", "-jar", "/app.jar"]
14+
VOLUME /tmp

build.gradle

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
plugins {
22
id 'java'
3-
id 'org.springframework.boot' version '2.7.15'
4-
id 'io.spring.dependency-management' version '1.0.15.RELEASE'
3+
id 'org.springframework.boot' version '2.7.14'
4+
id 'io.spring.dependency-management' version '1.1.3'
55
}
66

77
group = 'com.github'

docker-compose.yml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
version: '3'
2+
services:
3+
commerce:
4+
build:
5+
context: .
6+
dockerfile: Dockerfile
7+
restart: always
8+
ports:
9+
- "8080:8080"
10+
env_file:
11+
- .env
12+
13+
#version: '3'
14+
#services:
15+
# commerce:
16+
# image: zin354/commerce-consumer:latest
17+
# restart: always
18+
# ports:
19+
# - "8080:8080"
20+
# env_file:
21+
# - .env
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package com.github.messageconsumer.advice;
2+
3+
4+
import com.github.messageconsumer.advice.exception.ErrorResponse;
5+
import com.github.messageconsumer.advice.exception.type.ErrorCode;
6+
import com.github.messageconsumer.service.cart.exception.CartErrorResponse;
7+
import com.github.messageconsumer.service.cart.exception.CartException;
8+
import com.github.messageconsumer.service.order.exception.OrderErrorResponse;
9+
import com.github.messageconsumer.service.order.exception.OrderException;
10+
import lombok.extern.slf4j.Slf4j;
11+
import org.springframework.http.ResponseEntity;
12+
import org.springframework.http.converter.HttpMessageNotReadableException;
13+
import org.springframework.web.bind.MethodArgumentNotValidException;
14+
import org.springframework.web.bind.annotation.ExceptionHandler;
15+
import org.springframework.web.bind.annotation.RestControllerAdvice;
16+
17+
@Slf4j
18+
@RestControllerAdvice
19+
public class GlobalExceptionHandler {
20+
21+
@ExceptionHandler(MethodArgumentNotValidException.class)
22+
public ResponseEntity<?> handleValidationException(
23+
MethodArgumentNotValidException e
24+
){
25+
ErrorResponse errorResponse = new ErrorResponse(ErrorCode.BAD_REQUEST,
26+
e.getBindingResult().getAllErrors().get(0).getDefaultMessage());
27+
return ResponseEntity.badRequest().body(errorResponse);
28+
}
29+
30+
@ExceptionHandler(HttpMessageNotReadableException.class)
31+
public ResponseEntity<?> handleHttpMessageNotReadableException(
32+
HttpMessageNotReadableException e
33+
){
34+
ErrorResponse errorResponse = new ErrorResponse(ErrorCode.BAD_REQUEST,
35+
"Request Body가 비어 있습니다");
36+
return ResponseEntity.badRequest().body(errorResponse);
37+
}
38+
39+
@ExceptionHandler(CartException.class)
40+
public ResponseEntity<?> handleCartException(CartException e){
41+
42+
return ResponseEntity.status(e.getErrorCode().getHttpStatus())
43+
.body(CartErrorResponse.builder()
44+
.errorCode(e.getErrorCode())
45+
.errorMessage(e.getErrorMessage())
46+
.build());
47+
48+
}
49+
50+
@ExceptionHandler(OrderException.class)
51+
public ResponseEntity<?> handleOrderException(OrderException e){
52+
return ResponseEntity.status(e.getErrorCode().getHttpStatus())
53+
.body(OrderErrorResponse.builder()
54+
.errorCode(e.getErrorCode())
55+
.errorMessage(e.getErrorMessage())
56+
.build());
57+
}
58+
59+
60+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package com.github.messageconsumer.advice;
2+
3+
import lombok.RequiredArgsConstructor;
4+
import lombok.extern.slf4j.Slf4j;
5+
import org.aspectj.lang.annotation.Aspect;
6+
import org.aspectj.lang.annotation.Before;
7+
import org.springframework.stereotype.Component;
8+
9+
import javax.servlet.http.HttpServletRequest;
10+
11+
@Aspect
12+
@Component
13+
@RequiredArgsConstructor
14+
@Slf4j
15+
public class LoggingAspect {
16+
17+
private final HttpServletRequest request;
18+
19+
@Before("execution(* com.github.commerce..*Controller.*(..))")
20+
public void beforeAdvice() {
21+
String endpoint = request.getRequestURI(); // 현재 요청의 엔드포인트 경로를 얻어옴
22+
23+
log.info("\u001B[34mAPI 호출! - " + endpoint + "\u001B[0m");
24+
}
25+
26+
// @AfterReturning(pointcut = "execution(* com.github.commerce..*Controller.*(..))", returning = "returnValue")
27+
// public void afterAdvice(JoinPoint joinPoint, Object returnValue) {
28+
// String endpoint = request.getRequestURI(); // 현재 요청의 엔드포인트 경로를 얻어옴
29+
//
30+
// log.info("\u001B[32mAPI 호출 완료! - " + endpoint + " : "
31+
// + ((ResponseEntity<?>) returnValue).getBody() + "\u001B[0m");
32+
// }
33+
34+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package com.github.messageconsumer.advice.exception;
2+
3+
4+
import com.github.messageconsumer.advice.exception.type.ErrorCode;
5+
import lombok.*;
6+
7+
@Getter
8+
@Setter
9+
@AllArgsConstructor
10+
@NoArgsConstructor
11+
@Builder
12+
public class ErrorResponse {
13+
14+
private ErrorCode errorCode;
15+
private String errorMessage;
16+
17+
18+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package com.github.messageconsumer.advice.exception.type;
2+
3+
import lombok.AllArgsConstructor;
4+
import lombok.Getter;
5+
6+
@Getter
7+
@AllArgsConstructor
8+
public enum ErrorCode {
9+
10+
BAD_REQUEST("입력 값을 확인해 주세요.");
11+
private final String description;
12+
}

src/main/java/com/github/messageconsumer/config/RabbitMQConfig.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,11 @@
55
import org.springframework.amqp.core.BindingBuilder;
66
import org.springframework.amqp.core.DirectExchange;
77
import org.springframework.amqp.core.Queue;
8-
import org.springframework.amqp.core.TopicExchange;
98
import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory;
109
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
1110
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
1211
import org.springframework.amqp.rabbit.core.RabbitTemplate;
1312
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
14-
import org.springframework.amqp.support.converter.MessageConverter;
1513
import org.springframework.beans.factory.annotation.Value;
1614
import org.springframework.context.annotation.Bean;
1715
import org.springframework.context.annotation.Configuration;
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package com.github.messageconsumer.entity;
2+
3+
import lombok.*;
4+
5+
import javax.persistence.*;
6+
import java.time.LocalDateTime;
7+
8+
@Getter
9+
@Setter
10+
@NoArgsConstructor
11+
@AllArgsConstructor
12+
@Builder
13+
@Entity
14+
@Table(name = "failed_logs")
15+
public class FailedLog {
16+
@Id
17+
@GeneratedValue(strategy = GenerationType.IDENTITY)
18+
@Column(name = "id", nullable = false)
19+
private Long id;
20+
21+
@Column
22+
private String messageBody;
23+
24+
@Column
25+
private LocalDateTime createdAt;
26+
27+
}

src/main/java/com/github/messageconsumer/entity/Order.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ public class Order {
4040
private Integer quantity;
4141

4242
@Column(name= "total_price")
43-
private Integer total_price;
43+
private Integer totalPrice;
4444

4545
@Column(name="created_at")
4646
LocalDateTime createdAt;

src/main/java/com/github/messageconsumer/entity/Product.java

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import javax.validation.constraints.NotNull;
77
import javax.validation.constraints.Size;
88
import java.time.Instant;
9+
import java.time.LocalDateTime;
910

1011
@Getter
1112
@Setter
@@ -30,12 +31,10 @@ public class Product {
3031
@Column(name = "name", nullable = false)
3132
private String name;
3233

33-
@Lob
3434
@Column(name = "content")
3535
private String content;
3636

3737
@Size(max = 255)
38-
@NotNull
3938
@Column(name = "thumbnail_url", nullable = false)
4039
private String thumbnailUrl;
4140

@@ -48,25 +47,21 @@ public class Product {
4847

4948
@NotNull
5049
@Column(name = "created_at", nullable = false)
51-
private Instant createdAt;
50+
private LocalDateTime createdAt;
5251

5352
@Column(name = "updated_at")
54-
private Instant updatedAt;
53+
private LocalDateTime updatedAt;
5554

5655
@NotNull
5756
@Column(name = "is_deleted", nullable = false, columnDefinition = "tinyint default 0")
58-
private Boolean isDeleted;
57+
private Boolean isDeleted ;
5958

60-
@Lob
6159
@Column(name = "product_category")
6260
private String productCategory;
6361

64-
@Lob
6562
@Column(name = "gender_category")
6663
private String genderCategory;
6764

68-
@Lob
6965
@Column(name = "age_category")
7066
private String ageCategory;
71-
7267
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package com.github.messageconsumer.repository;
2+
3+
import com.github.messageconsumer.entity.FailedLog;
4+
import org.springframework.data.jpa.repository.JpaRepository;
5+
6+
public interface FailedLogRepository extends JpaRepository<FailedLog, Long> {
7+
}

src/main/java/com/github/messageconsumer/service/cart/CartConsumerService.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import com.github.messageconsumer.entity.User;
77
import com.github.messageconsumer.repository.CartRepository;
88
import com.github.messageconsumer.service.cart.util.ValidatCartMethod;
9+
import com.rabbitmq.client.AMQP;
910
import com.rabbitmq.client.Channel;
1011
import lombok.RequiredArgsConstructor;
1112
import lombok.extern.slf4j.Slf4j;
@@ -58,6 +59,10 @@ public void postCartQueue(CartRmqDto cartRmqDto, Message message, Channel channe
5859
// 최대 재시도 횟수를 초과하면 메시지를 버립니다.
5960
channel.basicReject(message.getMessageProperties().getDeliveryTag(), false);
6061
log.error("Max retries exceeded. Discarding message.");
62+
63+
String dlqExchange = "dlqExchange"; // DLQ로 메시지를 보낼 Exchange 이름
64+
String dlqRoutingKey = "dlq.postCart"; // DLQ로 메시지를 보낼 Routing Key
65+
channel.basicPublish(dlqExchange, dlqRoutingKey, null, message.getBody());
6166
}
6267
}
6368
}
@@ -92,6 +97,9 @@ public void putCartQueue(CartRmqDto cartRmqDto, Message message, Channel channel
9297
// 최대 재시도 횟수를 초과하면 메시지를 버립니다.
9398
channel.basicReject(message.getMessageProperties().getDeliveryTag(), false);
9499
log.error("Max retries exceeded. Discarding message.");
100+
String dlqExchange = "dlqExchange"; // DLQ로 메시지를 보낼 Exchange 이름
101+
String dlqRoutingKey = "dlq.putCart"; // DLQ로 메시지를 보낼 Routing Key
102+
channel.basicPublish(dlqExchange, dlqRoutingKey, null, message.getBody());
95103
}
96104
}
97105
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package com.github.messageconsumer.service.cart;
2+
3+
4+
import com.github.messageconsumer.entity.FailedLog;
5+
import com.github.messageconsumer.repository.FailedLogRepository;
6+
import lombok.RequiredArgsConstructor;
7+
import lombok.extern.slf4j.Slf4j;
8+
import org.springframework.amqp.core.Message;
9+
import org.springframework.amqp.rabbit.annotation.RabbitListener;
10+
import org.springframework.amqp.rabbit.core.RabbitTemplate;
11+
import org.springframework.messaging.handler.annotation.Payload;
12+
import org.springframework.stereotype.Service;
13+
14+
import java.io.IOException;
15+
import java.time.LocalDateTime;
16+
17+
@Slf4j
18+
@RequiredArgsConstructor
19+
@Service
20+
public class FailedCartService {
21+
22+
private final RabbitTemplate rabbitTemplate;
23+
private final FailedLogRepository failedLogRepository;
24+
25+
@RabbitListener(queues = "dlqCart", containerFactory = "rabbitListenerContainerFactory")
26+
public void getDlqCart(@Payload Message message){
27+
try {
28+
String messageBody = new String(message.getBody(), "UTF-8");
29+
30+
// 실패한 메시지를 데이터베이스에 저장
31+
FailedLog failedLog = new FailedLog();
32+
failedLog.setMessageBody(messageBody);
33+
failedLog.setCreatedAt(LocalDateTime.now());
34+
failedLogRepository.save(failedLog);
35+
36+
log.info("Failed Cart message saved to the database.");
37+
} catch (IOException e) {
38+
log.error("Error processing failed cart message: " + e.getMessage(), e);
39+
}
40+
41+
42+
}
43+
44+
}

src/main/java/com/github/messageconsumer/service/chat/ChatConsumerService.java

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,21 @@ public class ChatConsumerService {
3131
@RabbitListener(queues = "postRoom", containerFactory = "rabbitListenerContainerFactory")
3232
public void postRoom(RoomRmqDto roomRmqDto, Message message, Channel channel) throws IOException {
3333
try {
34-
Optional<Chat> chat = chatRepository.findByCustomRoomId(roomRmqDto.getCustomRoomId());
35-
if (chat.isPresent()) {
36-
// 이미 존재하는 경우 아무것도 하지 않고 성공 처리
37-
log.info("Chat already exists for customRoomId: " + roomRmqDto.getCustomRoomId());
34+
System.out.println("postRoom11111111111");
35+
Optional<Chat> chatOptional = chatRepository.findByCustomRoomId(roomRmqDto.getCustomRoomId());
36+
if (chatOptional.isPresent()) {
37+
Chat chat = chatOptional.get();
38+
// Chat 객체 업데이트
39+
chat.setSellerId(roomRmqDto.getSellerId());
40+
chat.setShopName(roomRmqDto.getShopName());
41+
chat.setUserId(roomRmqDto.getUserId());
42+
chat.setUserName(roomRmqDto.getUserName());
43+
chat.setProductId(roomRmqDto.getProductId());
44+
45+
chatRepository.save(chat); // Chat 업데이트 후 저장
46+
3847
} else {
48+
System.out.println("postRoom222222222");
3949
// 존재하지 않는 경우 새로운 Chat 객체 생성 및 저장
4050
Chat newChat = Chat.builder()
4151
.customRoomId(roomRmqDto.getCustomRoomId())

0 commit comments

Comments
 (0)