전 포스팅에서 비동기로 실행하여 하나의 쓰레드로 실행된 프로세스를 두개의 쓰레드로 나눠서 실행하였다. 그 결과, 프로세스 소요 시간을 줄이고, 전체 트랜잭션 롤백 문제를 해결할 수 있었다. 하지만 아직 하나의 문제가 남아있다.
이러한 문제는 @TransactionalEventListener를 사용하여 해결할 수 있다.
@TransactionalEventListener 어노테이션은 트랜잭션 이벤트 리스너를 등록하는데 사용된다. 트랜잭션의 특정한 상태(커밋, 롤백)에 따라 이벤트를 처리할 수 있다. 그 특정한 상태의 옵션을 확인해 보겠다.
phase = TransactionPhase.AFTER_COMMIT
default 값이며, 트랜잭션이 commit 되었을 때 이벤트를 실행한다.
phase = TransactionPhase.ROLLBACK
트랜잭션이 rollback 되었을 때 이벤트를 실행한다.
phase = TransactionPhase.AFTER_COMPLETION
트랜잭션이 completion(commit 또는 rollback) 되었을 때 이벤트를 실행한다.
phase = TransactionPhase.BEFORE_COMMIT
트랜잭션이 commit 되기 전에 이벤트를 실행한다.
출처: https://wildeveloperetrain.tistory.com/246
@Component
@RequiredArgsConstructor
@Slf4j
public class NotificationEventHandler {
private final NotificationUtils notificationUtils;
@TransactionalEventListener(
classes = NotificationEvent.class,
phase = TransactionPhase.AFTER_COMMIT)
@Async
public void sendNotification(NotificationEvent notificationEvent) {
notificationUtils
.sendNotification(
notificationEvent.getUser(),
notificationEvent.getReservationId(),
notificationEvent.getTitleMessage(),
notificationEvent.getContentMessage());
}
}
결과
커밋이 완료된 후에 이벤트가 발행되는 것을 확인할 수 있었다. 만약 약속방 삭제 프로세스가 정상적으로 동작이 안 될 경우에는 이벤트는 발행 되지만 이벤트리스너가 실행되지 않는다. 그럼 이제 모든 기능 구현이 완료되었다.