Skip to content

Commit d83b23f

Browse files
committed
feature: 상품 조회 이벤트(ProductViewEvent) 추가 및 Kafka 기반 조회 추적 기능 구현
- 상품 조회 액션을 기록하기 위한 ProductViewEvent 도입 - ProductViewEvent를 처리하고 Kafka와 연동하는 ProductEventOutboxHandler 구현 - 상품 정보 조회 시 ProductFacade에서 ProductViewEvent 발행하도록 수정 - 이벤트 저장, 중복 제거, Kafka 발행 로직 포함
1 parent a003ca3 commit d83b23f

3 files changed

Lines changed: 54 additions & 0 deletions

File tree

apps/commerce-api/src/main/java/com/loopers/application/product/ProductFacade.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@
33
import com.loopers.domain.brand.BrandService;
44
import com.loopers.domain.product.Product;
55
import com.loopers.domain.product.ProductService;
6+
import com.loopers.event.ProductViewEvent;
67
import lombok.RequiredArgsConstructor;
8+
import org.springframework.context.ApplicationEventPublisher;
79
import org.springframework.data.domain.Page;
810
import org.springframework.data.domain.Pageable;
911
import org.springframework.stereotype.Component;
@@ -14,6 +16,7 @@ public class ProductFacade {
1416

1517
private final ProductService productService;
1618
private final BrandService brandService;
19+
private final ApplicationEventPublisher eventPublisher;
1720

1821
public Page<ProductInfo> getProductsInfo(Pageable pageable) {
1922
Page<Product> products = productService.getProducts(pageable);
@@ -29,6 +32,8 @@ public ProductInfo getProductInfo(long id) {
2932
String brandName = brandService.getBrand(product.getBrandId())
3033
.getName();
3134

35+
eventPublisher.publishEvent(ProductViewEvent.from(id));
36+
3237
return ProductInfo.from(product, brandName);
3338
}
3439

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package com.loopers.application.product.event;
2+
3+
import com.loopers.domain.event.OutboxService;
4+
import com.loopers.event.ProductViewEvent;
5+
import lombok.RequiredArgsConstructor;
6+
import org.springframework.kafka.core.KafkaTemplate;
7+
import org.springframework.scheduling.annotation.Async;
8+
import org.springframework.stereotype.Component;
9+
import org.springframework.transaction.event.TransactionPhase;
10+
import org.springframework.transaction.event.TransactionalEventListener;
11+
12+
@Component
13+
@RequiredArgsConstructor
14+
public class ProductEventOutboxHandler {
15+
16+
private final OutboxService outboxService;
17+
private final KafkaTemplate<Object, Object> kafkaTemplate;
18+
19+
@Async
20+
@TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
21+
public void handle(ProductViewEvent event) {
22+
outboxService.saveEvent("PRODUCT_VIEW", String.valueOf(event.productId()), event);
23+
24+
kafkaTemplate.send("catalog-events", String.valueOf(event.productId()), event)
25+
.whenComplete((result, ex) -> {
26+
if (ex == null) {
27+
outboxService.markPublished(event.eventId());
28+
}
29+
});
30+
}
31+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package com.loopers.event;
2+
3+
import java.util.UUID;
4+
5+
public record ProductViewEvent(
6+
String eventId,
7+
Long productId,
8+
long timestamp
9+
) {
10+
11+
public static ProductViewEvent from(Long productId) {
12+
return new ProductViewEvent(
13+
UUID.randomUUID().toString(),
14+
productId,
15+
System.currentTimeMillis()
16+
);
17+
}
18+
}

0 commit comments

Comments
 (0)