1313import org .springframework .stereotype .Service ;
1414import org .springframework .transaction .annotation .Transactional ;
1515
16- import java .time .ZoneId ;
17- import java .time .ZonedDateTime ;
18-
1916/**
2017 * 메트릭 집계 서비스
2118 * - Kafka 이벤트를 받아서 ProductMetrics 테이블 업데이트
@@ -44,28 +41,16 @@ public void handleProductLiked(String eventId, ProductLikedEvent payload) {
4441 ProductMetrics metrics = metricsRepository .findById (payload .productId ())
4542 .orElse (ProductMetrics .create (payload .productId ()));
4643
47- ZonedDateTime eventOccurredAt = toZonedDateTime (payload .likedAt ());
48- boolean updated = metrics .incrementLikeCount (eventOccurredAt );
49-
50- if (!updated ) {
51- log .warn ("[Metrics] Out-of-order event ignored - eventId: {}, productId: {}, eventTime: {}, lastUpdated: {}" ,
52- eventId , payload .productId (), eventOccurredAt , metrics .getLastUpdated ());
53- // 오래된 이벤트도 처리 완료 기록 (재처리 방지)
54- eventHandledRepository .save (
55- EventHandled .create (eventId , "PRODUCT_LIKED" , String .valueOf (payload .productId ()))
56- );
57- return ;
58- }
59-
44+ metrics .incrementLikeCount ();
6045 metricsRepository .save (metrics );
6146
6247 // 처리 완료 기록
6348 eventHandledRepository .save (
6449 EventHandled .create (eventId , "PRODUCT_LIKED" , String .valueOf (payload .productId ()))
6550 );
6651
67- log .info ("[Metrics] Like count incremented - productId: {}, count: {}, eventTime: {} " ,
68- payload .productId (), metrics .getLikeCount (), eventOccurredAt );
52+ log .info ("[Metrics] Like count incremented - productId: {}, count: {}" ,
53+ payload .productId (), metrics .getLikeCount ());
6954 }
7055
7156 /**
@@ -82,28 +67,16 @@ public void handleProductUnliked(String eventId, ProductUnlikedEvent payload) {
8267 ProductMetrics metrics = metricsRepository .findById (payload .productId ())
8368 .orElse (ProductMetrics .create (payload .productId ()));
8469
85- ZonedDateTime eventOccurredAt = toZonedDateTime (payload .unlikedAt ());
86- boolean updated = metrics .decrementLikeCount (eventOccurredAt );
87-
88- if (!updated ) {
89- log .warn ("[Metrics] Out-of-order event ignored - eventId: {}, productId: {}, eventTime: {}, lastUpdated: {}" ,
90- eventId , payload .productId (), eventOccurredAt , metrics .getLastUpdated ());
91- // 오래된 이벤트도 처리 완료 기록 (재처리 방지)
92- eventHandledRepository .save (
93- EventHandled .create (eventId , "PRODUCT_UNLIKED" , String .valueOf (payload .productId ()))
94- );
95- return ;
96- }
97-
70+ metrics .decrementLikeCount ();
9871 metricsRepository .save (metrics );
9972
10073 // 처리 완료 기록
10174 eventHandledRepository .save (
10275 EventHandled .create (eventId , "PRODUCT_UNLIKED" , String .valueOf (payload .productId ()))
10376 );
10477
105- log .info ("[Metrics] Like count decremented - productId: {}, count: {}, eventTime: {} " ,
106- payload .productId (), metrics .getLikeCount (), eventOccurredAt );
78+ log .info ("[Metrics] Like count decremented - productId: {}, count: {}" ,
79+ payload .productId (), metrics .getLikeCount ());
10780 }
10881
10982 /**
@@ -116,38 +89,27 @@ public void handleOrderCompleted(String eventId, OrderCompletedEvent payload) {
11689 return ;
11790 }
11891
119- ZonedDateTime eventOccurredAt = toZonedDateTime (payload .completedAt ());
120- int updatedCount = 0 ;
121- int ignoredCount = 0 ;
122-
12392 // 각 주문 아이템별로 ProductMetrics 업데이트
12493 for (var item : payload .items ()) {
12594 ProductMetrics metrics = metricsRepository .findById (item .productId ())
12695 .orElse (ProductMetrics .create (item .productId ()));
12796
12897 // 판매 금액 = 수량 * 단가
12998 long totalAmount = item .quantity () * item .price ().longValue ();
130- boolean updated = metrics .addSales (item .quantity (), totalAmount , eventOccurredAt );
131-
132- if (updated ) {
133- metricsRepository .save (metrics );
134- updatedCount ++;
135- log .debug ("[Metrics] Sales updated - productId: {}, quantity: {}, amount: {}, eventTime: {}" ,
136- item .productId (), item .quantity (), totalAmount , eventOccurredAt );
137- } else {
138- ignoredCount ++;
139- log .warn ("[Metrics] Out-of-order sales event ignored - productId: {}, eventTime: {}, lastUpdated: {}" ,
140- item .productId (), eventOccurredAt , metrics .getLastUpdated ());
141- }
99+ metrics .addSales (item .quantity (), totalAmount );
100+ metricsRepository .save (metrics );
101+
102+ log .debug ("[Metrics] Sales updated - productId: {}, quantity: {}, amount: {}" ,
103+ item .productId (), item .quantity (), totalAmount );
142104 }
143105
144106 // 처리 완료 기록
145107 eventHandledRepository .save (
146108 EventHandled .create (eventId , "ORDER_COMPLETED" , payload .orderNo ())
147109 );
148110
149- log .info ("[Metrics] Sales aggregated for order: {} ({} items updated, {} ignored )" ,
150- payload .orderNo (), updatedCount , ignoredCount );
111+ log .info ("[Metrics] Sales aggregated for order: {} ({} items)" ,
112+ payload .orderNo (), payload . items (). size () );
151113 }
152114
153115 /**
@@ -164,34 +126,15 @@ public void handleProductViewed(String eventId, ProductViewedEvent payload) {
164126 ProductMetrics metrics = metricsRepository .findById (payload .productId ())
165127 .orElse (ProductMetrics .create (payload .productId ()));
166128
167- ZonedDateTime eventOccurredAt = toZonedDateTime (payload .viewedAt ());
168- boolean updated = metrics .incrementViewCount (eventOccurredAt );
169-
170- if (!updated ) {
171- log .warn ("[Metrics] Out-of-order event ignored - eventId: {}, productId: {}, eventTime: {}, lastUpdated: {}" ,
172- eventId , payload .productId (), eventOccurredAt , metrics .getLastUpdated ());
173- // 오래된 이벤트도 처리 완료 기록 (재처리 방지)
174- eventHandledRepository .save (
175- EventHandled .create (eventId , "PRODUCT_VIEWED" , String .valueOf (payload .productId ()))
176- );
177- return ;
178- }
179-
129+ metrics .incrementViewCount ();
180130 metricsRepository .save (metrics );
181131
182132 // 처리 완료 기록
183133 eventHandledRepository .save (
184134 EventHandled .create (eventId , "PRODUCT_VIEWED" , String .valueOf (payload .productId ()))
185135 );
186136
187- log .info ("[Metrics] View count incremented - productId: {}, count: {}, eventTime: {}" ,
188- payload .productId (), metrics .getViewCount (), eventOccurredAt );
189- }
190-
191- /**
192- * LocalDateTime을 ZonedDateTime으로 변환 (Asia/Seoul)
193- */
194- private ZonedDateTime toZonedDateTime (java .time .LocalDateTime localDateTime ) {
195- return localDateTime .atZone (ZoneId .of ("Asia/Seoul" ));
137+ log .info ("[Metrics] View count incremented - productId: {}, count: {}" ,
138+ payload .productId (), metrics .getViewCount ());
196139 }
197140}
0 commit comments