/**
* 거래 완료 메시지 전송 Listener
*/
@RabbitListener(
queues = {"#{wasteCompleteQueue.name}", "#{wasteCancelQueue.name}", "#{wasteChangeStatusQueue.name}"})
public void receiveWasteTransaction(@Payload MessageRequest messageRequest) {
log.debug("receive complete transaction message");
Alarm alarm = saveAlarm(messageRequest);
receive(messageRequest.memberId(), AlarmResponse.fromEntity(alarm));
}
/**
* SSE 알람 전송
* @param memberId 알람을 받는 사용자 id
*/
private void receive(Long memberId, AlarmResponse alarmResponse) {
if (true) throw new RuntimeException(); //ListenerExecutionFailedException
}
위처럼 중간에 임의로 예외(ListenerExecutionFailedException
)를 발생시킬 경우 무한 재실행이 된다. DB를 확인해보면 데이터가 계속 추가되는 것을 확인할 수 있었다.
공식 문서를 확인해보면 다음과 같은 문장을 볼 수 있었다.
Consequently, by default, a message that is rejected or rolled back because of a business exception can be redelivered endlessly.
끊임없이 redeliver를 한다고 한다. 만약 re-deliver 횟수를 제한하고 싶다면 StatefulRetryOperationsInterceptor
을 사용하라고 한다.
하지만 더 간단한 방법으로 properties 값을 설정해줄 수 있다.
spring:
config.activate.on-profile: amqp
rabbitmq:
listener:
simple:
retry:
enabled: true
max-attempts: 3
이렇게 설정해주면 3번 redeliver를 해주게된다. 위처럼 max-attempts
만 지정해주면 1초 간격으로 retry를 한다.
또한 다음과 같이 RetryTemplate
을 사용해줄 수 있다.
@Bean
public RabbitTemplate rabbitTemplate() {
RabbitTemplate template = new RabbitTemplate(connectionFactory());
RetryTemplate retryTemplate = new RetryTemplate();
ExponentialBackOffPolicy backOffPolicy = new ExponentialBackOffPolicy();
backOffPolicy.setInitialInterval(500);
backOffPolicy.setMultiplier(10.0);
backOffPolicy.setMaxInterval(10000);
retryTemplate.setBackOffPolicy(backOffPolicy);
template.setRetryTemplate(retryTemplate);
return template;
}
여기서 retryCallback을 추가해줄 수 있다고 한다.
RetryTemplate.execute(RetryCallback<T, E> retryCallback, RecoveryCallback<T> recoveryCallback)