From 8344a67c42544b5472a542157a3afccf6809f652 Mon Sep 17 00:00:00 2001
From: Jaejun Lee <110995932+jooooonj@users.noreply.github.com>
Date: Fri, 15 Sep 2023 19:13:37 +0900
Subject: [PATCH 01/14] Update README.md
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index ef9d4082..4bea3329 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-## ๐ TrendPick, ์ทจํฅ์ ๋ง๊ฒ ์ํ์ ์ถ์ฒ ํด์ฃผ๋ ์๋น์ค
+## ๐ TrendPick, ์ทจํฅ์ ๋ง๊ฒ ์ํ์ ์ถ์ฒ ํด์ฃผ๋ ์๋น์ค
From 2d43ceb6afc3308f993657972d0fba044b557dcb Mon Sep 17 00:00:00 2001
From: Jaejun Lee <110995932+jooooonj@users.noreply.github.com>
Date: Fri, 15 Sep 2023 19:14:26 +0900
Subject: [PATCH 02/14] Update work-2.yml
---
.github/workflows/work-2.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/work-2.yml b/.github/workflows/work-2.yml
index 13e89225..edf5aa34 100644
--- a/.github/workflows/work-2.yml
+++ b/.github/workflows/work-2.yml
@@ -15,7 +15,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- - name: application-secret.yml ์์ฑ
+ - name: application-secret.yml ์์ฑํ๋ค.
env:
ACTIONS_STEP_DEBUG: true
APPLICATION_SECRET: ${{ secrets.APPLICATION_SECRET_YML }}
From 131f1c8e872ec01f7ca60cffbf4adf7690b1f82f Mon Sep 17 00:00:00 2001
From: jooooonj
Date: Tue, 19 Sep 2023 18:29:36 +0900
Subject: [PATCH 03/14] =?UTF-8?q?refactor:=20=EC=A1=B0=ED=9A=8C=EC=88=98?=
=?UTF-8?q?=20=EA=B0=B1=EC=8B=A0=20=EA=B8=B0=EB=8A=A5=20=EC=82=AD=EC=A0=9C?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../global/basedata/BaseData.java | 6 ---
.../global/kafka/view/entity/View.java | 23 ----------
.../kafka/view/repository/ViewRepository.java | 7 ---
.../kafka/view/service/ViewService.java | 46 -------------------
4 files changed, 82 deletions(-)
delete mode 100644 src/main/java/project/trendpick_pro/global/kafka/view/entity/View.java
delete mode 100644 src/main/java/project/trendpick_pro/global/kafka/view/repository/ViewRepository.java
delete mode 100644 src/main/java/project/trendpick_pro/global/kafka/view/service/ViewService.java
diff --git a/src/main/java/project/trendpick_pro/global/basedata/BaseData.java b/src/main/java/project/trendpick_pro/global/basedata/BaseData.java
index 99e63e21..93ea5dbd 100644
--- a/src/main/java/project/trendpick_pro/global/basedata/BaseData.java
+++ b/src/main/java/project/trendpick_pro/global/basedata/BaseData.java
@@ -24,7 +24,6 @@
import project.trendpick_pro.domain.common.file.CommonFile;
import project.trendpick_pro.domain.coupon.entity.expirationPeriod.ExpirationType;
import project.trendpick_pro.domain.store.service.StoreService;
-import project.trendpick_pro.global.kafka.view.service.ViewService;
import project.trendpick_pro.domain.coupon.entity.Coupon;
import project.trendpick_pro.domain.coupon.entity.dto.request.StoreCouponSaveRequest;
import project.trendpick_pro.domain.coupon.repository.CouponRepository;
@@ -99,7 +98,6 @@ CommandLineRunner initData(
BrandService brandService,
ProductService productService,
StoreService storeService,
- ViewService viewService,
ProductRepository productRepository,
ReviewRepository reviewRepository,
CouponRepository couponRepository,
@@ -138,10 +136,6 @@ public void run(String... args) {
saveReviews(reviewCount, productCount, accessKeyMap, memberService, productService ,reviewRepository);
saveStoreCoupon(couponCount, storeRepository, couponRepository, brandService);
- if (viewService.findSize() == 0) {
- viewService.registerView();
- }
-
log.info("BASE_DATA_SUCCESS");
}
};
diff --git a/src/main/java/project/trendpick_pro/global/kafka/view/entity/View.java b/src/main/java/project/trendpick_pro/global/kafka/view/entity/View.java
deleted file mode 100644
index 6366ce14..00000000
--- a/src/main/java/project/trendpick_pro/global/kafka/view/entity/View.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package project.trendpick_pro.global.kafka.view.entity;
-
-import jakarta.persistence.Entity;
-import jakarta.persistence.GeneratedValue;
-import jakarta.persistence.GenerationType;
-import jakarta.persistence.Id;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-
-@Entity
-@Getter
-@NoArgsConstructor
-public class View {
-
- @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
- private Long id;
-
- private Long count = 0L;
-
- public void increment() {
- this.count++;
- }
-}
diff --git a/src/main/java/project/trendpick_pro/global/kafka/view/repository/ViewRepository.java b/src/main/java/project/trendpick_pro/global/kafka/view/repository/ViewRepository.java
deleted file mode 100644
index d972c81c..00000000
--- a/src/main/java/project/trendpick_pro/global/kafka/view/repository/ViewRepository.java
+++ /dev/null
@@ -1,7 +0,0 @@
-package project.trendpick_pro.global.kafka.view.repository;
-
-import org.springframework.data.jpa.repository.JpaRepository;
-import project.trendpick_pro.global.kafka.view.entity.View;
-
-public interface ViewRepository extends JpaRepository {
-}
diff --git a/src/main/java/project/trendpick_pro/global/kafka/view/service/ViewService.java b/src/main/java/project/trendpick_pro/global/kafka/view/service/ViewService.java
deleted file mode 100644
index 37c417b2..00000000
--- a/src/main/java/project/trendpick_pro/global/kafka/view/service/ViewService.java
+++ /dev/null
@@ -1,46 +0,0 @@
-package project.trendpick_pro.global.kafka.view.service;
-
-import jakarta.servlet.http.HttpSession;
-import lombok.RequiredArgsConstructor;
-import org.springframework.kafka.core.KafkaTemplate;
-import org.springframework.scheduling.annotation.Async;
-import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
-import project.trendpick_pro.global.kafka.view.entity.View;
-import project.trendpick_pro.global.kafka.view.repository.ViewRepository;
-
-@Transactional(readOnly = true)
-@Service
-@RequiredArgsConstructor
-public class ViewService {
-
- private final ViewRepository viewRepository;
-
- private final KafkaTemplate kafkaTemplate;
-
- @Transactional
- public void registerView() {
- viewRepository.save(new View());
- }
-
- public int findSize() {
- return viewRepository.findAll().size();
- }
-
- @Async
- public void requestIncrementViewCount(HttpSession session) {
- if (session.getAttribute("visited") == null) {
- kafkaTemplate.send("views", "increment", "1");
- session.setAttribute("visited", true);
- }
- }
-
- @Transactional
- public void incrementViewCount(String viewId) {
- viewRepository.findById(Long.valueOf(viewId)).get().increment();
- }
-
- public Long getCount() {
- return viewRepository.findById(1L).get().getCount();
- }
-}
From 9a610faec74f23223c571052efce0f9590395bd8 Mon Sep 17 00:00:00 2001
From: jooooonj
Date: Tue, 19 Sep 2023 18:39:26 +0900
Subject: [PATCH 04/14] =?UTF-8?q?refactor:=20=EC=9E=84=EC=8B=9C=20?=
=?UTF-8?q?=EC=83=81=ED=83=9C=EC=9D=98=20=EC=A3=BC=EB=AC=B8=20=EA=B0=9D?=
=?UTF-8?q?=EC=B2=B4=20=EC=83=9D=EC=84=B1=20=ED=95=A8=EC=88=98=20=EC=B6=94?=
=?UTF-8?q?=EA=B0=80?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../common/controller/CommonController.java | 4 ----
.../domain/orders/entity/Order.java | 20 +++++++++++++------
2 files changed, 14 insertions(+), 10 deletions(-)
diff --git a/src/main/java/project/trendpick_pro/domain/common/controller/CommonController.java b/src/main/java/project/trendpick_pro/domain/common/controller/CommonController.java
index 3aa7ec07..d759bb0f 100644
--- a/src/main/java/project/trendpick_pro/domain/common/controller/CommonController.java
+++ b/src/main/java/project/trendpick_pro/domain/common/controller/CommonController.java
@@ -6,18 +6,14 @@
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.util.UriComponentsBuilder;
-import project.trendpick_pro.global.kafka.view.service.ViewService;
@Slf4j
@Controller
@RequiredArgsConstructor
public class CommonController {
- private final ViewService viewService;
-
@GetMapping("/")
public String homePage(HttpSession session) {
- viewService.requestIncrementViewCount(session);
String mainCategory = "์ ์ฒด";
return "redirect:" + UriComponentsBuilder
.fromPath("/trendpick/products/list")
diff --git a/src/main/java/project/trendpick_pro/domain/orders/entity/Order.java b/src/main/java/project/trendpick_pro/domain/orders/entity/Order.java
index b34dc0e5..8de538ac 100644
--- a/src/main/java/project/trendpick_pro/domain/orders/entity/Order.java
+++ b/src/main/java/project/trendpick_pro/domain/orders/entity/Order.java
@@ -39,7 +39,7 @@ public class Order extends BaseTimeEntity {
@Enumerated(EnumType.STRING)
private OrderStatus orderStatus;
- @Column(name = "total_price", nullable = false)
+ @Column(name = "total_price")
private int totalPrice = 0;
public void connectUser(Member member) {
@@ -49,7 +49,7 @@ public void connectUser(Member member) {
public void connectPayment(String paymentMethod, String paymentKey) {
this.paymentMethod = paymentMethod;
this.paymentKey = paymentKey;
- productDiscount();
+ setDiscountAmount();
}
public void connectDelivery(Delivery delivery) {
@@ -66,6 +66,15 @@ public static Order createOrder(Member member, Delivery delivery, List orderItems) {
+ public void settingOrderItems(List orderItems) {
for (OrderItem orderItem : orderItems) {
this.addOrderItem(orderItem);
this.totalPrice += orderItem.getTotalPrice();
From 60f3172d1efeea53dce220700fa894114df3fee2 Mon Sep 17 00:00:00 2001
From: jooooonj
Date: Tue, 19 Sep 2023 18:40:16 +0900
Subject: [PATCH 05/14] =?UTF-8?q?refactor:=20orderItem=20=EB=82=B4?=
=?UTF-8?q?=EB=B6=80=EC=97=90=EC=84=9C=20=EC=9E=AC=EA=B3=A0=20=EC=B2=98?=
=?UTF-8?q?=EB=A6=AC=EB=A5=BC=20=ED=95=98=EB=8F=84=EB=A1=9D=20=EB=B3=80?=
=?UTF-8?q?=EA=B2=BD?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../domain/orders/entity/OrderItem.java | 13 ++++++-------
1 file changed, 6 insertions(+), 7 deletions(-)
diff --git a/src/main/java/project/trendpick_pro/domain/orders/entity/OrderItem.java b/src/main/java/project/trendpick_pro/domain/orders/entity/OrderItem.java
index fd7bcfec..df3d1378 100644
--- a/src/main/java/project/trendpick_pro/domain/orders/entity/OrderItem.java
+++ b/src/main/java/project/trendpick_pro/domain/orders/entity/OrderItem.java
@@ -8,6 +8,7 @@
import project.trendpick_pro.domain.common.base.BaseTimeEntity;
import project.trendpick_pro.domain.coupon.entity.CouponCard;
import project.trendpick_pro.domain.product.entity.product.Product;
+import project.trendpick_pro.domain.product.exception.ProductStockOutException;
@Entity
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@@ -69,21 +70,19 @@ public void connectOrder(Order order) {
public void applyCouponCard(CouponCard couponCard) {
this.couponCard = couponCard;
int discountPercent = couponCard.getCoupon().getDiscountPercent();
- int price = getOrderPrice() * discountPercent / 100; //์ฟ ํฐ์ ์ํ ํ ๊ฐ ๊ฐ๊ฒฉ์์ ํ ์ธ ์ ์ฉ
- discount(price);
+ this.discountPrice = getOrderPrice() * discountPercent / 100; //์ฟ ํฐ์ ์ํ ํ ๊ฐ ๊ฐ๊ฒฉ์์ ํ ์ธ ์ ์ฉ
+ this.totalPrice -= this.discountPrice;
}
public void cancelCouponCard(){
this.couponCard = null;
+ this.totalPrice += this.discountPrice;
this.discountPrice = 0;
}
- private void discount(int price){
- this.discountPrice += price;
- this.totalPrice -= this.discountPrice;
- }
-
private OrderItem(Product product, int quantity, String size, String color) {
+ if(product.getProductOption().getStock() < quantity)
+ throw new ProductStockOutException("์ํ์ ์ฌ๊ณ ๊ฐ ๋ถ์กฑํ์ฌ ์ฃผ๋ฌธ์ด ๋ถ๊ฐ๋ฅํฉ๋๋ค.");
this.product = product;
this.orderPrice = (product.getDiscountedPrice() > 0) ? product.getDiscountedPrice() : product.getProductOption().getPrice();
this.quantity = quantity;
From 7e8e03ae38c0fd6f6f2119021a5c457a7e6510f4 Mon Sep 17 00:00:00 2001
From: jooooonj
Date: Tue, 19 Sep 2023 18:49:05 +0900
Subject: [PATCH 06/14] =?UTF-8?q?refactor:=20=EC=A3=BC=EB=AC=B8=20?=
=?UTF-8?q?=EA=B0=9D=EC=B2=B4=EC=9D=98=20=EC=83=81=ED=83=9C=EC=97=90=20?=
=?UTF-8?q?=EB=94=B0=EB=A5=B8=20=EC=B2=98=EB=A6=AC=20(=EC=9E=84=EC=8B=9C?=
=?UTF-8?q?=20=EC=A3=BC=EB=AC=B8=20=EC=82=AD=EC=A0=9C,=20=EC=A4=91?=
=?UTF-8?q?=EB=B3=B5=20=EC=B2=98=EB=A6=AC=20=EB=B0=A9=EC=A7=80)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../domain/orders/contoller/OrderController.java | 6 +++++-
.../domain/orders/repository/OrderRepository.java | 10 ++++++++++
.../job/cancelOrderJobConfig/CancelOrderJobConfig.java | 4 ++--
3 files changed, 17 insertions(+), 3 deletions(-)
diff --git a/src/main/java/project/trendpick_pro/domain/orders/contoller/OrderController.java b/src/main/java/project/trendpick_pro/domain/orders/contoller/OrderController.java
index b2a6622c..cb380d30 100644
--- a/src/main/java/project/trendpick_pro/domain/orders/contoller/OrderController.java
+++ b/src/main/java/project/trendpick_pro/domain/orders/contoller/OrderController.java
@@ -7,6 +7,7 @@
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import project.trendpick_pro.domain.member.entity.Member;
+import project.trendpick_pro.domain.orders.entity.Order;
import project.trendpick_pro.domain.orders.entity.dto.request.CartToOrderRequest;
import project.trendpick_pro.domain.orders.entity.dto.request.ProductOrderRequest;
import project.trendpick_pro.domain.orders.entity.dto.response.OrderDetailResponse;
@@ -28,7 +29,10 @@ public class OrderController {
@PreAuthorize("hasAuthority({'MEMBER'})")
@GetMapping("{orderId}/form")
public String showOrderForm(@PathVariable("orderId") Long orderId, Model model){
- model.addAttribute("order", orderService.findById(orderId));
+ Order order = orderService.findById(orderId);
+ if(order.getPaymentKey() != null || order.getOrderState().equals("์ฃผ๋ฌธ์ทจ์"))
+ return rq.redirectWithMsg("/", "์ด๋ฏธ ์ฒ๋ฆฌ๋ ์ฃผ๋ฌธ์
๋๋ค.");
+ model.addAttribute("order", order);
return "trendpick/orders/order-form";
}
diff --git a/src/main/java/project/trendpick_pro/domain/orders/repository/OrderRepository.java b/src/main/java/project/trendpick_pro/domain/orders/repository/OrderRepository.java
index d72dbd7f..738a4923 100644
--- a/src/main/java/project/trendpick_pro/domain/orders/repository/OrderRepository.java
+++ b/src/main/java/project/trendpick_pro/domain/orders/repository/OrderRepository.java
@@ -1,7 +1,17 @@
package project.trendpick_pro.domain.orders.repository;
import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.query.Param;
import project.trendpick_pro.domain.orders.entity.Order;
+import java.time.LocalDateTime;
+import java.util.List;
+
public interface OrderRepository extends JpaRepository, OrderRepositoryCustom {
+
+ @Query("SELECT o FROM Order o " +
+ "WHERE o.paymentKey IS NULL " +
+ "AND o.createdDate < :date")
+ List findAllByPaymentKeyIsNullAndCreatedDateIsBefore(@Param("date") LocalDateTime date);
}
diff --git a/src/main/java/project/trendpick_pro/global/job/cancelOrderJobConfig/CancelOrderJobConfig.java b/src/main/java/project/trendpick_pro/global/job/cancelOrderJobConfig/CancelOrderJobConfig.java
index 21b834b8..db3d0df6 100644
--- a/src/main/java/project/trendpick_pro/global/job/cancelOrderJobConfig/CancelOrderJobConfig.java
+++ b/src/main/java/project/trendpick_pro/global/job/cancelOrderJobConfig/CancelOrderJobConfig.java
@@ -71,9 +71,9 @@ public RepositoryItemReader orderReader(
return new RepositoryItemReaderBuilder()
.name("orderReader")
.repository(orderRepository)
- .methodName("findAllByStatusAndCreatedDateIsBefore")
+ .methodName("findAllByPaymentKeyIsNullAndCreatedDateIsBefore")
.pageSize(100)
- .arguments(Arrays.asList(OrderStatus.TEMP, date))
+ .arguments(Arrays.asList(date))
.sorts(Collections.singletonMap("id", Sort.Direction.ASC))
.build();
}
From 0877564c639490f7955cd2909366a0dc8df9b900 Mon Sep 17 00:00:00 2001
From: jooooonj
Date: Tue, 19 Sep 2023 18:50:39 +0900
Subject: [PATCH 07/14] =?UTF-8?q?refactor:=20OrderService=20=EC=BD=94?=
=?UTF-8?q?=EB=93=9C=20=EC=A0=95=EB=A6=AC=20/=20OrderMaterial=20=EB=8F=84?=
=?UTF-8?q?=EC=9E=85?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../domain/orders/service/OrderService.java | 3 +-
.../orders/service/impl/OrderServiceImpl.java | 165 ++++++++----------
.../kafka/outbox/entity/OrderMaterial.java | 37 ++++
3 files changed, 107 insertions(+), 98 deletions(-)
create mode 100644 src/main/java/project/trendpick_pro/global/kafka/outbox/entity/OrderMaterial.java
diff --git a/src/main/java/project/trendpick_pro/domain/orders/service/OrderService.java b/src/main/java/project/trendpick_pro/domain/orders/service/OrderService.java
index 8b79a6c0..6f6ee020 100644
--- a/src/main/java/project/trendpick_pro/domain/orders/service/OrderService.java
+++ b/src/main/java/project/trendpick_pro/domain/orders/service/OrderService.java
@@ -8,6 +8,7 @@
import project.trendpick_pro.domain.orders.entity.dto.request.CartToOrderRequest;
import project.trendpick_pro.domain.orders.entity.dto.response.OrderDetailResponse;
import project.trendpick_pro.domain.orders.entity.dto.response.OrderResponse;
+import project.trendpick_pro.global.kafka.outbox.entity.OrderMaterial;
import project.trendpick_pro.global.util.rsData.RsData;
import java.time.LocalDate;
@@ -17,7 +18,7 @@
public interface OrderService {
RsData cartToOrder(Member member, CartToOrderRequest request);
RsData productToOrder(Member member, Long id, int quantity, String size, String color);
- void tryOrder(String id) throws JsonProcessingException;
+ void tryOrder(String id, List orderMaterials) throws JsonProcessingException;
RsData cancel(Long orderId);
void delete(Long id);
RsData findOrderItems(Member member, Long orderId);
diff --git a/src/main/java/project/trendpick_pro/domain/orders/service/impl/OrderServiceImpl.java b/src/main/java/project/trendpick_pro/domain/orders/service/impl/OrderServiceImpl.java
index 76adb52b..eff83baf 100644
--- a/src/main/java/project/trendpick_pro/domain/orders/service/impl/OrderServiceImpl.java
+++ b/src/main/java/project/trendpick_pro/domain/orders/service/impl/OrderServiceImpl.java
@@ -1,13 +1,12 @@
package project.trendpick_pro.domain.orders.service.impl;
import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
+import org.jetbrains.annotations.Nullable;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
-import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import project.trendpick_pro.domain.cart.entity.CartItem;
@@ -21,23 +20,17 @@
import project.trendpick_pro.domain.orders.entity.OrderStatus;
import project.trendpick_pro.domain.orders.entity.dto.request.CartToOrderRequest;
import project.trendpick_pro.domain.orders.entity.dto.request.OrderSearchCond;
-import project.trendpick_pro.domain.orders.entity.dto.request.OrderStateResponse;
import project.trendpick_pro.domain.orders.entity.dto.response.OrderDetailResponse;
import project.trendpick_pro.domain.orders.entity.dto.response.OrderResponse;
import project.trendpick_pro.domain.orders.exception.OrderNotFoundException;
import project.trendpick_pro.domain.orders.repository.OrderItemRepository;
import project.trendpick_pro.domain.orders.repository.OrderRepository;
import project.trendpick_pro.domain.orders.service.OrderService;
-import project.trendpick_pro.domain.product.entity.product.Product;
-import project.trendpick_pro.domain.product.entity.productOption.ProductOption;
-import project.trendpick_pro.domain.product.exception.ProductNotFoundException;
import project.trendpick_pro.domain.product.exception.ProductStockOutException;
import project.trendpick_pro.domain.product.service.ProductService;
-import project.trendpick_pro.domain.tags.favoritetag.service.FavoriteTagService;
-import project.trendpick_pro.domain.tags.tag.entity.TagType;
import project.trendpick_pro.global.kafka.KafkaProducerService;
-import project.trendpick_pro.global.kafka.kafkasave.entity.OutboxMessage;
-import project.trendpick_pro.global.kafka.kafkasave.service.OutboxMessageService;
+import project.trendpick_pro.global.kafka.outbox.entity.OrderMaterial;
+import project.trendpick_pro.global.kafka.outbox.service.OutboxMessageService;
import project.trendpick_pro.global.util.rsData.RsData;
import java.time.LocalDate;
@@ -59,76 +52,60 @@ public class OrderServiceImpl implements OrderService {
private final CartService cartService;
private final ProductService productService;
- private final FavoriteTagService favoriteTagService;
-
private final OutboxMessageService outboxMessageService;
-
private final KafkaProducerService kafkaProducerService;
@Transactional
public RsData cartToOrder(Member member, CartToOrderRequest request) {
- if(member.getAddress().trim().isEmpty()) {
- return RsData.of("F-1", "์ฃผ์๋ฅผ ์ ์ ์์ด ์ฃผ๋ฌธ์ด ๋ถ๊ฐ๋ฅํฉ๋๋ค.");
- }
- if(request.getSelectedItems().isEmpty()){
- return RsData.of("F-1","์ํ์ ์ ํํ ํ ์ฃผ๋ฌธํด์ฃผ์ธ์.");
- }
List cartItems = cartService.getSelectedCartItems(member, request);
- if (!Objects.equals(cartItems.get(0).getCart().getMember().getId(), member.getId())) {
- return RsData.of("F-1", "ํ์ฌ ์ ์์ค์ธ ์ฌ์ฉ์์ ์ฅ๋ฐ๊ตฌ๋ ์ฌ์ฉ์๊ฐ ์ผ์นํ์ง ์์ต๋๋ค.");
- }
- Order order = createOrder(member, cartItems);
+ RsData result = validateCartToOrder(member, request, cartItems);
+ if (result.isFail()) return result;
- OutboxMessage message = createOutboxMessage(order);
- kafkaProducerService.sendMessage(message.getId());
+ Order order = orderRepository.save(Order.createTempOrder(member, new Delivery(member.getAddress())));
+ String uuidCode = UUID.randomUUID().toString();
+
+ List orderMaterials = new ArrayList<>();
+ for (CartItem cartItem : cartItems)
+ orderMaterials.add(new OrderMaterial(cartItem, uuidCode));
+ outboxMessageService.publishOrderCreationMessage("orders", String.valueOf(order.getId()), orderMaterials, uuidCode);
return RsData.of("S-1", "์ฃผ๋ฌธ์ ์์ ํฉ๋๋ค.");
}
@Transactional
public RsData productToOrder(Member member, Long productId, int quantity, String size, String color) {
- try {
- Order saveOrder = orderRepository.save(
- Order.createOrder(member, new Delivery(member.getAddress()),
- List.of(OrderItem.of(productService.findById(productId), quantity, size, color))
- )
- );
- log.info("์ฌ๊ณ : {}", saveOrder.getOrderItems().get(0).getProduct().getProductOption().getStock());
- OutboxMessage message = createOutboxMessage(saveOrder);
- kafkaProducerService.sendMessage(message.getId());
- return RsData.of("S-1", "์ฃผ๋ฌธ์ ์์ํฉ๋๋ค.");
- } catch (ProductNotFoundException e) {
- return RsData.of("F-1", "์กด์ฌํ์ง ์๋ ์ํ์
๋๋ค.");
- }
+ String uuidCode = UUID.randomUUID().toString();
+
+ Order order = orderRepository.save(
+ Order.createTempOrder(member, new Delivery(member.getAddress())));
+
+ List orderMaterials = List.of(new OrderMaterial(productId, quantity, size, color, uuidCode));
+ outboxMessageService.publishOrderCreationMessage("orders", String.valueOf(order.getId()), orderMaterials, uuidCode);
+ return RsData.of("S-1", "์ฃผ๋ฌธ์ ์์ํฉ๋๋ค.");
}
- @Transactional
- public void tryOrder(String id) throws JsonProcessingException {
- Order order = orderRepository.findById(Long.parseLong(id))
- .orElseThrow(() -> new OrderNotFoundException("์กด์ฌํ์ง ์๋ ์ฃผ๋ฌธ ์
๋๋ค."));
- String email = order.getMember().getEmail();
- try {
+ @Transactional //์ค์ ์ฃผ๋ฌธ ๋ก์ง (์ฌ๊ณ ์ ํจ์ฑ ๊ฒ์ฌ, ์ฌ๊ณ ๊ฐ์, ์ํ ๋ณ๊ฒฝ)
+ public void tryOrder(String id, List orderMaterials) throws JsonProcessingException {
+ Order order = findById(Long.valueOf(id));
+ if(order.getOrderState().equals("๊ฒฐ์ ์๋ฃ")) //๋ฉฑ๋ฑ์ฑ
+ throw new IllegalAccessError("์ด๋ฏธ ์ฒ๋ฆฌ๋ ์ฃผ๋ฌธ์
๋๋ค.");
+
+ try{
+ List orderItems = OrderMaterialsToOrderItems(orderMaterials);
+ order.settingOrderItems(orderItems);
order.updateStatus(OrderStatus.ORDERED);
- sendMessage(order.getId(), "Success", email);
- } catch (ProductStockOutException e) {
- if (order.getOrderStatus() == OrderStatus.TEMP) {
- order.cancelTemp();
- }
- log.error("์ฃผ๋ฌธ ์คํจ : {}", e.getMessage());
- sendMessage(order.getId(), "Fail", email);
+ outboxMessageService.publishOrderProcessMessage("standByOrder", "Success", String.valueOf(order.getId()), order.getMember().getEmail());
+ } catch(ProductStockOutException e){
+ log.error("error message : {} ", e.getMessage());
+ kafkaProducerService.sendOrderProcessFailMessage(order.getId(), "Fail", order.getMember().getEmail());
}
}
@Transactional
public RsData cancel(Long orderId) {
- Order order = orderRepository.findById(orderId).orElseThrow(() -> new OrderNotFoundException("์กด์ฌํ์ง ์๋ ์ฃผ๋ฌธ์
๋๋ค."));
- if(order.getOrderStatus() == OrderStatus.CANCELED) {
- return RsData.of("F-1", "์ด๋ฏธ ์ทจ์๋ ์ฃผ๋ฌธ์
๋๋ค.");
- } else if (order.getDelivery().getState() == DeliveryState.COMPLETED) {
- return RsData.of("F-2", "์ด๋ฏธ ๋ฐฐ์ก์๋ฃ๋ ์ํ์ ์ทจ์๊ฐ ๋ถ๊ฐ๋ฅํฉ๋๋ค.");
- }
- if (order.getDelivery().getState() == DeliveryState.DELIVERY_ING) {
- return RsData.of("F-3", "์ด๋ฏธ ๋ฐฐ์ก์ ์์ํ์ฌ ์ทจ์๊ฐ ๋ถ๊ฐ๋ฅํฉ๋๋ค.");
- }
+ Order order = findById(orderId);
+ RsData result = validateAvailableCancel(order);
+ if (result.isFail()) return result;
+
order.cancel();
return RsData.of("S-1", "ํ๋ถ ์์ฒญ์ด ์ ์์ ์ผ๋ก ์งํ ๋์์ต๋๋ค. ํ๋ถ๊น์ง๋ ์ต์ 2์ผ์์ ์ต๋ 14์ผ๊น์ง ์์๋ ์ ์์ต๋๋ค.");
}
@@ -143,7 +120,6 @@ public RsData findOrderItems(Member member, Long orderId) {
try {
Order order = orderRepository.findById(orderId).orElseThrow(() -> new OrderNotFoundException("์กด์ฌํ์ง ์๋ ์ฃผ๋ฌธ ์
๋๋ค."));
if (order.getOrderStatus() == OrderStatus.TEMP) {
- orderRepository.delete(order);
return RsData.of("F-3", "์กด์ฌํ์ง ์๋ ์ฃผ๋ฌธ์
๋๋ค.");
}
if (!Objects.equals(order.getMember().getId(), member.getId())) {
@@ -180,41 +156,6 @@ public List findAllByCreatedDateBetweenOrderByIdAsc(LocalDateTime fro
return orderItemRepository.findAllByCreatedDateBetween(fromDate, toDate);
}
- private Order createOrder(Member member, List cartItems) {
- List orderItems = createOrderItem(member, cartItems);
- Order order = Order.createOrder(member, new Delivery(member.getAddress()), orderItems);
- return orderRepository.save(order);
- }
-
- private List createOrderItem(Member member, List cartItems) {
- List orderItems = new ArrayList<>();
- for (CartItem cartItem : cartItems) {
- Product product = checkingProductStock(cartItem);
- favoriteTagService.updateTag(member, product, TagType.ORDER);
- orderItems.add(OrderItem.of(product, cartItem));
- }
- return orderItems;
- }
-
- private Product checkingProductStock(CartItem cartItem) {
- Product product = productService.findById(cartItem.getProduct().getId());
- if (product.getProductOption().getStock() < cartItem.getQuantity()) {
- throw new ProductStockOutException("์ฌ๊ณ ๊ฐ ๋ถ์กฑํฉ๋๋ค.");
- }
- return product;
- }
-
- private OutboxMessage createOutboxMessage(Order order) {
- OutboxMessage message = new OutboxMessage("orders",
- String.valueOf(order.getId()), String.valueOf(order.getId()));
- outboxMessageService.save(message);
- return message;
- }
-
- private void sendMessage(Long orderId, String message, String email) throws JsonProcessingException {
- kafkaProducerService.sendMessage(orderId, message, email);
- }
-
private Page settingOrderByMemberStatus(Member member, int offset) {
Page findOrders;
PageRequest pageable = PageRequest.of(offset, 10);
@@ -228,9 +169,39 @@ private Page settingOrderByMemberStatus(Member member, int offset
return findOrders;
}
- private static List checkingTempStatus(Page findOrders) {
+ private List checkingTempStatus(Page findOrders) {
return findOrders.stream()
.filter(orderResponse -> !Objects.equals(orderResponse.getOrderStatus(), OrderStatus.TEMP.toString()))
.collect(Collectors.toList());
}
+
+ private RsData validateCartToOrder(Member member, CartToOrderRequest request, List cartItems) {
+ if(member.getAddress().trim().isEmpty())
+ return RsData.of("F-1", "์ฃผ์๋ฅผ ์ ์ ์์ด ์ฃผ๋ฌธ์ด ๋ถ๊ฐ๋ฅํฉ๋๋ค.");
+
+ if(request.getSelectedItems().isEmpty())
+ return RsData.of("F-1", "์ํ์ ์ ํํ ํ ์ฃผ๋ฌธํด์ฃผ์ธ์.");
+
+ if (!Objects.equals(cartItems.get(0).getCart().getMember().getId(), member.getId()))
+ return RsData.of("F-1", "ํ์ฌ ์ ์์ค์ธ ์ฌ์ฉ์์ ์ฅ๋ฐ๊ตฌ๋ ์ฌ์ฉ์๊ฐ ์ผ์นํ์ง ์์ต๋๋ค.");
+ return RsData.success();
+ }
+
+ private List OrderMaterialsToOrderItems(List orderMaterials) throws ProductStockOutException{
+ List orderItems = new ArrayList<>();
+ for (OrderMaterial orderMaterial : orderMaterials) { //์ด๋ ์ฌ๊ณ ๊ฐ์, ์ฌ๊ณ ์ฒดํฌ
+ orderItems.add(OrderItem.of(productService.findById(orderMaterial.getProductId()), orderMaterial.getQuantity(),
+ orderMaterial.getSize(), orderMaterial.getColor()));
+ }
+ return orderItems;
+ }
+
+ private RsData validateAvailableCancel(Order order) {
+ if(order.getOrderStatus() == OrderStatus.CANCELED)
+ return RsData.of("F-1", "์ด๋ฏธ ์ทจ์๋ ์ฃผ๋ฌธ์
๋๋ค.");
+
+ if (order.getDelivery().getState() == DeliveryState.DELIVERY_ING)
+ return RsData.of("F-3", "์ด๋ฏธ ๋ฐฐ์ก์ ์์ํ์ฌ ์ทจ์๊ฐ ๋ถ๊ฐ๋ฅํฉ๋๋ค.");
+ return RsData.success();
+ }
}
\ No newline at end of file
diff --git a/src/main/java/project/trendpick_pro/global/kafka/outbox/entity/OrderMaterial.java b/src/main/java/project/trendpick_pro/global/kafka/outbox/entity/OrderMaterial.java
new file mode 100644
index 00000000..a20e7bc7
--- /dev/null
+++ b/src/main/java/project/trendpick_pro/global/kafka/outbox/entity/OrderMaterial.java
@@ -0,0 +1,37 @@
+package project.trendpick_pro.global.kafka.outbox.entity;
+
+import jakarta.persistence.*;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import project.trendpick_pro.domain.cart.entity.CartItem;
+
+@AllArgsConstructor
+@NoArgsConstructor
+@Getter
+@Entity
+public class OrderMaterial {
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private Long id;
+ private Long productId;
+ private Integer quantity;
+ private String size;
+ private String color;
+ private String code;
+ @ManyToOne(fetch = FetchType.EAGER)
+ @JoinColumn(name = "outbox_message_id")
+ private OutboxMessage outboxMessage;
+
+ public OrderMaterial(Long productId, Integer quantity, String size, String color, String code) {
+ this.productId = productId;
+ this.quantity = quantity;
+ this.size = size;
+ this.color = color;
+ this.code = code;
+ }
+
+ public OrderMaterial(CartItem cartItem, String code){
+ new OrderMaterial(cartItem.getProduct().getId(), cartItem.getQuantity(), cartItem.getSize(), cartItem.getColor(), code);
+ }
+}
From 3cd2e80c5450bc1b186c562d0fca423a8f10813e Mon Sep 17 00:00:00 2001
From: jooooonj
Date: Tue, 19 Sep 2023 18:51:50 +0900
Subject: [PATCH 08/14] =?UTF-8?q?refactor:=20=EC=95=84=EC=9B=83=20?=
=?UTF-8?q?=EB=B0=95=EC=8A=A4=20=ED=8C=A8=ED=84=B4=20=EC=82=AC=EC=9A=A9=20?=
=?UTF-8?q?=EC=9A=A9=EB=8F=84=20=EB=B3=80=EA=B2=BD=20(=ED=8A=B8=EB=9E=9C?=
=?UTF-8?q?=EC=9E=AD=EC=85=98=20=EB=AC=B6=EA=B8=B0)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../global/kafka/KafkaProducerService.java | 66 +++++++++++++++----
.../kafka/kafkasave/entity/OutboxMessage.java | 29 --------
.../repository/OutboxMessageRepository.java | 7 --
.../service/OutboxMessageService.java | 31 ---------
.../kafka/outbox/entity/OutboxMessage.java | 55 ++++++++++++++++
.../repository/OutboxMessageRepository.java | 16 +++++
.../outbox/service/OutboxMessageService.java | 56 ++++++++++++++++
7 files changed, 180 insertions(+), 80 deletions(-)
delete mode 100644 src/main/java/project/trendpick_pro/global/kafka/kafkasave/entity/OutboxMessage.java
delete mode 100644 src/main/java/project/trendpick_pro/global/kafka/kafkasave/repository/OutboxMessageRepository.java
delete mode 100644 src/main/java/project/trendpick_pro/global/kafka/kafkasave/service/OutboxMessageService.java
create mode 100644 src/main/java/project/trendpick_pro/global/kafka/outbox/entity/OutboxMessage.java
create mode 100644 src/main/java/project/trendpick_pro/global/kafka/outbox/repository/OutboxMessageRepository.java
create mode 100644 src/main/java/project/trendpick_pro/global/kafka/outbox/service/OutboxMessageService.java
diff --git a/src/main/java/project/trendpick_pro/global/kafka/KafkaProducerService.java b/src/main/java/project/trendpick_pro/global/kafka/KafkaProducerService.java
index b3708125..536c0725 100644
--- a/src/main/java/project/trendpick_pro/global/kafka/KafkaProducerService.java
+++ b/src/main/java/project/trendpick_pro/global/kafka/KafkaProducerService.java
@@ -6,13 +6,15 @@
import lombok.extern.slf4j.Slf4j;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.retry.support.RetryTemplate;
-import org.springframework.scheduling.annotation.Async;
+import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import project.trendpick_pro.domain.orders.entity.dto.request.OrderStateResponse;
-import project.trendpick_pro.global.kafka.kafkasave.entity.OutboxMessage;
-import project.trendpick_pro.global.kafka.kafkasave.service.OutboxMessageService;
+import project.trendpick_pro.global.kafka.outbox.entity.OutboxMessage;
+import project.trendpick_pro.global.kafka.outbox.service.OutboxMessageService;
+import java.util.ArrayList;
+import java.util.List;
import java.util.UUID;
@Slf4j
@@ -28,12 +30,47 @@ public class KafkaProducerService {
private final ObjectMapper objectMapper;
@Transactional
- public void sendMessage(Long id) {
- OutboxMessage outboxMessage = outboxMessageService.findById(id);
+ @Scheduled(fixedRate = 3000) //3์ด๋ง๋ค ์์๋ฐ์ค๋ฅผ ์กฐํํ๋ฉฐ ๋ฉ์์ง๋ฅผ ๋ณด๋ธ๋ค.
+ public void sendMessage() throws JsonProcessingException {
+ List outboxMessages = outboxMessageService.findAll();
+
+ List completedMessages = new ArrayList<>();
+ for (OutboxMessage outboxMessage : outboxMessages) {
+ if(outboxMessage.getTopic().equals("standByOrder")) //์ฃผ๋ฌธ ์ฒ๋ฆฌ ์ฑ๊ณต ๋ฉ์์ง
+ sendOrderProcessSuccessMessage(completedMessages, outboxMessage);
+
+ else if(outboxMessage.getTopic().equals("orders"))
+ sendCompleteOrderCreationMessage(completedMessages, outboxMessage); //์ฃผ๋ฌธ ๊ฐ์ฒด ์์ฑ ์๋ฃ ๋ฉ์์ง
+ }
+
+ if(!completedMessages.isEmpty())
+ outboxMessageService.deleteAllById(completedMessages);
+ }
+
+ private void sendCompleteOrderCreationMessage(List completedMessages, OutboxMessage outboxMessage) {
retryTemplate.execute(context -> {
- kafkaTemplate.send(outboxMessage.getTopic(), outboxMessage.getPayload(), outboxMessage.getMessage());
- log.info("Message sent: {}", outboxMessage.getMessage());
- outboxMessageService.delete(outboxMessage);
+ kafkaTemplate.send(outboxMessage.getTopic(), outboxMessage.getPayload(), outboxMessage.getCode());
+ outboxMessage.disconnectOrderMaterial();
+ completedMessages.add(outboxMessage.getId());
+ log.info("Message sent: {}", outboxMessage.getMessage());
+ return null;
+ }, context -> {
+ log.error("Failed to send message: {}", context.getLastThrowable().getMessage());
+ return null;
+ });
+ }
+
+ @Transactional
+ public void sendOrderProcessFailMessage(Long orderId, String message, String email) throws JsonProcessingException {
+ OrderStateResponse response = OrderStateResponse.builder()
+ .orderId(orderId)
+ .message(message)
+ .email(email)
+ .build();
+ String json = objectMapper.writeValueAsString(response);
+ retryTemplate.execute(context -> {
+ kafkaTemplate.send("standByOrder", UUID.randomUUID().toString(), json);
+ log.info("Message sent: {}", message);
return null;
}, context -> {
log.error("Failed to send message: {}", context.getLastThrowable().getMessage());
@@ -42,20 +79,23 @@ public void sendMessage(Long id) {
}
@Transactional
- public void sendMessage(Long orderId, String message, String email) throws JsonProcessingException {
+ public void sendOrderProcessSuccessMessage(List completedMessages, OutboxMessage outboxMessage) throws JsonProcessingException {
OrderStateResponse response = OrderStateResponse.builder()
- .orderId(orderId)
- .message(message)
- .email(email)
+ .orderId(Long.valueOf(outboxMessage.getPayload()))
+ .message(outboxMessage.getMessage())
+ .email( outboxMessage.getEmail())
.build();
String json = objectMapper.writeValueAsString(response);
retryTemplate.execute(context -> {
kafkaTemplate.send("standByOrder", UUID.randomUUID().toString(), json);
- log.info("Message sent: {}", message);
+ completedMessages.add(outboxMessage.getId());
+ log.info("Message sent: {}", outboxMessage.getMessage());
return null;
}, context -> {
log.error("Failed to send message: {}", context.getLastThrowable().getMessage());
return null;
});
}
+
+
}
diff --git a/src/main/java/project/trendpick_pro/global/kafka/kafkasave/entity/OutboxMessage.java b/src/main/java/project/trendpick_pro/global/kafka/kafkasave/entity/OutboxMessage.java
deleted file mode 100644
index 448da8fa..00000000
--- a/src/main/java/project/trendpick_pro/global/kafka/kafkasave/entity/OutboxMessage.java
+++ /dev/null
@@ -1,29 +0,0 @@
-package project.trendpick_pro.global.kafka.kafkasave.entity;
-
-import jakarta.persistence.*;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-
-@Entity
-@Getter
-@NoArgsConstructor(access = lombok.AccessLevel.PROTECTED)
-public class OutboxMessage {
-
- @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
- private Long id;
-
- @Column(name = "topic", nullable = false)
- private String topic;
-
- @Column(name = "message", nullable = false)
- private String message;
-
- @Column(name = "payload", nullable = false)
- private String payload;
-
- public OutboxMessage(String topic, String message, String payload) {
- this.topic = topic;
- this.message = message;
- this.payload = payload;
- }
-}
diff --git a/src/main/java/project/trendpick_pro/global/kafka/kafkasave/repository/OutboxMessageRepository.java b/src/main/java/project/trendpick_pro/global/kafka/kafkasave/repository/OutboxMessageRepository.java
deleted file mode 100644
index 5b97efb9..00000000
--- a/src/main/java/project/trendpick_pro/global/kafka/kafkasave/repository/OutboxMessageRepository.java
+++ /dev/null
@@ -1,7 +0,0 @@
-package project.trendpick_pro.global.kafka.kafkasave.repository;
-
-import org.springframework.data.jpa.repository.JpaRepository;
-import project.trendpick_pro.global.kafka.kafkasave.entity.OutboxMessage;
-
-public interface OutboxMessageRepository extends JpaRepository {
-}
diff --git a/src/main/java/project/trendpick_pro/global/kafka/kafkasave/service/OutboxMessageService.java b/src/main/java/project/trendpick_pro/global/kafka/kafkasave/service/OutboxMessageService.java
deleted file mode 100644
index 89bb9b1e..00000000
--- a/src/main/java/project/trendpick_pro/global/kafka/kafkasave/service/OutboxMessageService.java
+++ /dev/null
@@ -1,31 +0,0 @@
-package project.trendpick_pro.global.kafka.kafkasave.service;
-
-import lombok.RequiredArgsConstructor;
-import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
-import project.trendpick_pro.global.kafka.kafkasave.entity.OutboxMessage;
-import project.trendpick_pro.global.kafka.kafkasave.repository.OutboxMessageRepository;
-
-import java.util.List;
-
-@Service
-@RequiredArgsConstructor
-public class OutboxMessageService {
-
- private final OutboxMessageRepository outboxMessageRepository;
-
- @Transactional
- public void save(OutboxMessage outboxMessage) {
- outboxMessageRepository.save(outboxMessage);
- }
-
- @Transactional
- public void delete(OutboxMessage outboxMessage) {
- outboxMessageRepository.delete(outboxMessage);
- }
-
- @Transactional(readOnly = true)
- public OutboxMessage findById(Long id) {
- return outboxMessageRepository.findById(id).get();
- }
-}
diff --git a/src/main/java/project/trendpick_pro/global/kafka/outbox/entity/OutboxMessage.java b/src/main/java/project/trendpick_pro/global/kafka/outbox/entity/OutboxMessage.java
new file mode 100644
index 00000000..c739f7b1
--- /dev/null
+++ b/src/main/java/project/trendpick_pro/global/kafka/outbox/entity/OutboxMessage.java
@@ -0,0 +1,55 @@
+package project.trendpick_pro.global.kafka.outbox.entity;
+
+import jakarta.persistence.*;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import project.trendpick_pro.domain.orders.entity.dto.response.OrderItemDto;
+import project.trendpick_pro.domain.product.entity.product.Product;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Entity
+@Getter
+@NoArgsConstructor(access = lombok.AccessLevel.PROTECTED)
+public class OutboxMessage {
+
+ @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private Long id;
+
+ @Column(name = "topic", nullable = false)
+ private String topic;
+
+ @Column(name = "message", nullable = false)
+ private String message;
+
+ @Column(name = "payload", nullable = false)
+ private String payload;
+
+ private String code;
+
+ private String email;
+
+ @OneToMany(mappedBy = "outboxMessage", cascade = CascadeType.PERSIST)
+ private List orderMaterials = new ArrayList<>();
+
+ public void disconnectOrderMaterial(){
+ this.orderMaterials = null;
+ }
+
+ public OutboxMessage (String topic, String message, String payload,
+ List orderMaterial, String code) {
+ this.topic = topic;
+ this.message = message;
+ this.payload = payload;
+ this.orderMaterials = orderMaterial;
+ this.code = code;
+ }
+
+ public OutboxMessage (String topic, String message, String payload, String email) {
+ this.topic = topic;
+ this.message = message;
+ this.payload = payload;
+ this.email = email;
+ }
+}
diff --git a/src/main/java/project/trendpick_pro/global/kafka/outbox/repository/OutboxMessageRepository.java b/src/main/java/project/trendpick_pro/global/kafka/outbox/repository/OutboxMessageRepository.java
new file mode 100644
index 00000000..14bb6975
--- /dev/null
+++ b/src/main/java/project/trendpick_pro/global/kafka/outbox/repository/OutboxMessageRepository.java
@@ -0,0 +1,16 @@
+package project.trendpick_pro.global.kafka.outbox.repository;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.query.Param;
+import project.trendpick_pro.global.kafka.outbox.entity.OrderMaterial;
+import project.trendpick_pro.global.kafka.outbox.entity.OutboxMessage;
+
+import java.util.List;
+import java.util.Optional;
+
+public interface OutboxMessageRepository extends JpaRepository {
+
+ @Query("select o from OrderMaterial o where o.code = :code")
+ List findAllOrderMaterialByCode(@Param("code") String code);
+}
diff --git a/src/main/java/project/trendpick_pro/global/kafka/outbox/service/OutboxMessageService.java b/src/main/java/project/trendpick_pro/global/kafka/outbox/service/OutboxMessageService.java
new file mode 100644
index 00000000..cd9f802e
--- /dev/null
+++ b/src/main/java/project/trendpick_pro/global/kafka/outbox/service/OutboxMessageService.java
@@ -0,0 +1,56 @@
+package project.trendpick_pro.global.kafka.outbox.service;
+
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import project.trendpick_pro.domain.orders.entity.Order;
+import project.trendpick_pro.global.kafka.outbox.entity.OrderMaterial;
+import project.trendpick_pro.global.kafka.outbox.entity.OutboxMessage;
+import project.trendpick_pro.global.kafka.outbox.repository.OutboxMessageRepository;
+
+import java.util.List;
+
+@Service
+@RequiredArgsConstructor
+@Transactional(readOnly = true)
+public class OutboxMessageService {
+
+ private final OutboxMessageRepository outboxMessageRepository;
+
+ public OutboxMessage findById(Long id) {
+ return outboxMessageRepository.findById(id).get();
+ }
+
+ public List findAll() {
+ return outboxMessageRepository.findAll();
+ }
+
+ @Transactional
+ public void save(OutboxMessage outboxMessage) {
+ outboxMessageRepository.save(outboxMessage);
+ }
+
+ @Transactional
+ public void delete(OutboxMessage outboxMessage) {
+ outboxMessageRepository.delete(outboxMessage);
+ }
+
+ @Transactional
+ public void deleteAllById(List completedMessages) {
+ outboxMessageRepository.deleteAllById(completedMessages);
+ }
+
+ public List findOrderMaterial(String code){
+ return outboxMessageRepository.findAllOrderMaterialByCode(code);
+ }
+
+ //์ฃผ๋ฌธ ๊ฐ์ณ ์์ฑ ๋ฉ์์ง ๋ฐํ
+ public void publishOrderCreationMessage(String topic, String key, List orderMaterials, String code) {
+ outboxMessageRepository.save(new OutboxMessage(topic, key, key, orderMaterials, code));
+ }
+
+ //์ฃผ๋ฌธ ์ฒ๋ฆฌ ๋ฉ์์ง ๋ฐํ
+ public void publishOrderProcessMessage(String topic, String message, String payload, String email) {
+ outboxMessageRepository.save(new OutboxMessage(topic, message, payload, email));
+ }
+}
From 3c5c4f938a6f5676d757a019d79a3d40bd99e3d7 Mon Sep 17 00:00:00 2001
From: jooooonj
Date: Tue, 19 Sep 2023 18:54:21 +0900
Subject: [PATCH 09/14] =?UTF-8?q?refactor:=20=EB=A9=94=EC=84=B8=EC=A7=80?=
=?UTF-8?q?=20=EC=B2=98=EB=A6=AC=20/=20=EB=B6=84=EC=82=B0=20=EB=9D=BD=20?=
=?UTF-8?q?=EB=B3=80=EA=B2=BD=20(=EC=A3=BC=EB=AC=B8=20->=20=EC=A3=BC?=
=?UTF-8?q?=EB=AC=B8=EC=83=81=ED=92=88)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../product/controller/ProductController.java | 6 --
.../global/kafka/KafkaConsumerService.java | 18 ++----
.../redisson/service/RedissonService.java | 59 ++++++++++++++-----
.../templates/trendpick/products/list.html | 5 --
4 files changed, 49 insertions(+), 39 deletions(-)
diff --git a/src/main/java/project/trendpick_pro/domain/product/controller/ProductController.java b/src/main/java/project/trendpick_pro/domain/product/controller/ProductController.java
index 68067a0f..ef0301f8 100644
--- a/src/main/java/project/trendpick_pro/domain/product/controller/ProductController.java
+++ b/src/main/java/project/trendpick_pro/domain/product/controller/ProductController.java
@@ -20,7 +20,6 @@
import project.trendpick_pro.domain.category.service.SubCategoryService;
import project.trendpick_pro.global.basedata.tagname.service.impl.TagNameServiceImpl;
import project.trendpick_pro.global.util.rq.Rq;
-import project.trendpick_pro.global.kafka.view.service.ViewService;
import project.trendpick_pro.domain.member.entity.Member;
import project.trendpick_pro.domain.member.service.MemberService;
import project.trendpick_pro.domain.product.entity.dto.ProductRequest;
@@ -60,8 +59,6 @@ public class ProductController {
private final ReviewService reviewService;
private final AskService askService;
- private final ViewService viewService;
-
private final Rq rq;
@Value("${colors}")
@@ -133,8 +130,6 @@ public String showAllProduct(@RequestParam(value = "page", defaultValue = "0") i
@RequestParam(value = "main-category", defaultValue = "all") String mainCategory,
@RequestParam(value = "sub-category", defaultValue = "์ ์ฒด") String subCategory,
Pageable pageable, Model model, HttpSession session) {
- viewService.requestIncrementViewCount(session);
- model.addAttribute("totalView", viewService.getCount());
if (mainCategory.equals("recommend")) {
mainCategory = "์ถ์ฒ";
} else if (mainCategory.equals("all")) {
@@ -179,7 +174,6 @@ public String showAllProductBySeller(@RequestParam("page") int offset, Model mod
@GetMapping("/keyword")
public String searchQuery(@RequestParam String keyword, @RequestParam(value = "page", defaultValue = "0") int offset, Model model) {
Page products = productService.findAllByKeyword(keyword, offset);
- model.addAttribute("totalView", viewService.getCount());
model.addAttribute("keyword", keyword);
model.addAttribute("productResponses", products);
return "trendpick/products/list";
diff --git a/src/main/java/project/trendpick_pro/global/kafka/KafkaConsumerService.java b/src/main/java/project/trendpick_pro/global/kafka/KafkaConsumerService.java
index 12f9b3ec..14134d0d 100644
--- a/src/main/java/project/trendpick_pro/global/kafka/KafkaConsumerService.java
+++ b/src/main/java/project/trendpick_pro/global/kafka/KafkaConsumerService.java
@@ -10,8 +10,8 @@
import org.springframework.messaging.handler.annotation.Payload;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.stereotype.Service;
+import project.trendpick_pro.domain.orders.service.OrderService;
import project.trendpick_pro.global.redis.redisson.service.RedissonService;
-import project.trendpick_pro.global.kafka.view.service.ViewService;
import project.trendpick_pro.domain.orders.entity.dto.request.OrderStateResponse;
@Slf4j
@@ -20,19 +20,18 @@
public class KafkaConsumerService {
private final RedissonService redissonService;
- private final ViewService viewService;
-
private final SimpMessagingTemplate messagingTemplate;
private final ObjectMapper objectMapper;
-
+ private final OrderService orderService;
@KafkaListener(topics = "orders", groupId = "order")
public void orderToOrder(ConsumerRecord message, Acknowledgment ack) {
try {
- redissonService.processOrderWithLock(message.key());
- ack.acknowledge();
+ redissonService.processOrderWithLock(message.key(), message.value());
} catch (Exception e) {
- log.error(e.getMessage());
+ log.error("orderToOrder process error : {} ", e.getMessage());
+ } finally {
+ ack.acknowledge();
}
}
@@ -41,9 +40,4 @@ public void message(@Payload String json) throws JsonProcessingException {
OrderStateResponse response = objectMapper.readValue(json, OrderStateResponse.class);
messagingTemplate.convertAndSendToUser(response.getEmail(), "/topic/standByOrder", json);
}
-
- @KafkaListener(topicPattern = "views", groupId = "view")
- public void handleIncrementViewCount(@Payload String viewId) {
- viewService.incrementViewCount(viewId);
- }
}
diff --git a/src/main/java/project/trendpick_pro/global/redis/redisson/service/RedissonService.java b/src/main/java/project/trendpick_pro/global/redis/redisson/service/RedissonService.java
index 8d27d775..d0d265d5 100644
--- a/src/main/java/project/trendpick_pro/global/redis/redisson/service/RedissonService.java
+++ b/src/main/java/project/trendpick_pro/global/redis/redisson/service/RedissonService.java
@@ -1,46 +1,73 @@
package project.trendpick_pro.global.redis.redisson.service;
-import com.fasterxml.jackson.core.JsonProcessingException;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Service;
+import project.trendpick_pro.domain.orders.entity.Order;
import project.trendpick_pro.domain.orders.service.OrderService;
-import project.trendpick_pro.domain.product.exception.ProductStockOutException;
+import project.trendpick_pro.global.kafka.outbox.entity.OrderMaterial;
+import project.trendpick_pro.global.kafka.outbox.service.OutboxMessageService;
import project.trendpick_pro.global.redis.exception.RedisLockException;
-
+import java.util.ArrayList;
+import java.util.List;
import java.util.concurrent.TimeUnit;
@Slf4j
@Service
@RequiredArgsConstructor
public class RedissonService {
-
private final RedissonClient redissonClient;
private final OrderService orderService;
+ private final OutboxMessageService outboxMessageService;
- public void processOrderWithLock(String orderKey) throws InterruptedException {
- RLock lock = getDistributedLock(orderKey);
- if (lock.tryLock(3, 3, TimeUnit.SECONDS)) {
- try {
- log.info(lock.getName());
- orderService.tryOrder(orderKey);
- } catch (JsonProcessingException e) {
+ public void processOrderWithLock(String orderId, String orderMaterialCode) throws InterruptedException {
+ Order order = orderService.findById(Long.valueOf(orderId));
+ List orderMaterials = outboxMessageService.findOrderMaterial(orderMaterialCode);
+ List locks = getLocks(orderMaterials); //์ฃผ๋ฌธ ์ํ๋ค์ ๋ํ ๋ฝ
+ if (isCompleteLock(locks))
+ try{
+ orderService.tryOrder(orderId, orderMaterials);
+ } catch (Exception e){
log.error("Error processing order", e);
- } finally {;
+ } finally {
try {
- lock.unlock();
+ unlock(locks);
} catch (IllegalMonitorStateException e) {
log.info("Redisson Lock Already UnLocked");
}
}
- } else {
- throw new RedisLockException("ํด๋น ๋ฝ์ด ์ฌ์ฉ์ค์
๋๋ค");
+ else throw new RedisLockException("ํด๋น ๋ฝ์ด ์ฌ์ฉ์ค์
๋๋ค");
+ }
+
+ private List getLocks(List orderMaterials) {
+ List lockList = new ArrayList<>();
+ for(OrderMaterial orderMaterial : orderMaterials)
+ lockList.add(getDistributedLock(String.valueOf(orderMaterial.getProductId())));
+ return lockList;
+ }
+
+ private boolean isCompleteLock(List lockList) throws InterruptedException {
+ for (RLock lock : lockList) {
+ if(!lock.tryLock(3, 1, TimeUnit.SECONDS)){
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public void unlock(List lockList){
+ for (RLock lock : lockList){
+ try {
+ lock.unlock();
+ } catch (IllegalMonitorStateException e) {
+ log.info("Redisson Lock Already UnLocked");
+ }
}
}
private RLock getDistributedLock(String key) {
- return redissonClient.getLock("ORD_" + key);
+ return redissonClient.getLock("PRODUCT_" + key);
}
}
diff --git a/src/main/resources/templates/trendpick/products/list.html b/src/main/resources/templates/trendpick/products/list.html
index 039217dc..90886e59 100644
--- a/src/main/resources/templates/trendpick/products/list.html
+++ b/src/main/resources/templates/trendpick/products/list.html
@@ -163,11 +163,6 @@
-
-