ReservationNotificationHandler.java
package com.deveagles.be15_deveagles_be.features.schedules.command.application.handler;
import com.deveagles.be15_deveagles_be.common.events.ReservationCreatedEvent;
import com.deveagles.be15_deveagles_be.features.notifications.command.application.dto.CreateNotificationRequest;
import com.deveagles.be15_deveagles_be.features.notifications.command.application.service.NotificationCommandService;
import com.deveagles.be15_deveagles_be.features.notifications.command.application.service.NotificationSseService;
import com.deveagles.be15_deveagles_be.features.notifications.command.domain.aggregate.NotificationType;
import com.deveagles.be15_deveagles_be.features.notifications.query.application.dto.NotificationResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.transaction.event.TransactionalEventListener;
@Slf4j
@Component
@RequiredArgsConstructor
public class ReservationNotificationHandler {
private final NotificationCommandService notificationCommandService;
private final NotificationSseService notificationSseService;
// @EventListener 를 @TransactionalEventListener 로 변경하여
// 예약 정보가 DB에 100% 안전하게 저장된 후에만 아래 코드를 실행하도록 보장합니다.
@TransactionalEventListener
public void handle(ReservationCreatedEvent event) {
log.info("[Event] ReservationCreatedEvent 수신 - shopId: {}", event.shopId());
// 1. 알림 생성에 필요한 데이터를 가공합니다.
CreateNotificationRequest request =
new CreateNotificationRequest(
event.shopId(),
NotificationType.RESERVATION,
"새로운 예약 신청",
String.format("고객 '%s'님이 예약을 신청했습니다. 확인해주세요.", event.customerName()));
// 2. 알림을 DB에 저장하고, 저장된 알림 정보를 반환받습니다.
NotificationResponse savedNotification = notificationCommandService.create(request);
// 3. ✨ [핵심 해결책] 저장된 알림 정보를 클라이언트에게 실시간으로 발송합니다.
// 이 코드가 없으면 알림은 DB에만 저장되고 프론트엔드로는 절대 전송되지 않습니다.
if (savedNotification != null) {
notificationSseService.send(event.shopId(), savedNotification);
}
}
}