首页 > 解决方案 > Retry for specific exception in Reactor

问题描述

I have microservices application. For collaborating each service uses async messaging. I know, that spring data jpa uses optimistic lock by default. But in case of this lock in methods called not by user, but by another service (in my example there are validation services, that can update status of object to valid or non valid) I want to handle exception and retry to update object. Also I had to use webflux stack on this microservice. Now i have such code:

public void updateStatus(String id, EventStatus status) {
    eventRepository.findById(id)
            .doOnNext(eventDocument -> {
                eventDocument.setStatus(status);
                eventRepository.save(eventDocument).subscribe();
            }).doOnError(OptimisticLockingFailureException.class, exception -> { //Retry in 2 sec if optimistic lock occurs on update
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException ex) {
                    ex.printStackTrace();
                }
                updateStatus(id, status);
            })
            .subscribe();
}

I don't like recursion here. Is there any better solution for this?

标签: javaspringspring-data-jpaspring-webfluxproject-reactor

解决方案


The following retries every 2 seconds in case OptimisticLockingFailureException is thrown.

private static final int MAX_ATTEMPTS = Integer.MAX_VALUE;

public void updateStatus(String id, EventStatus status) {
    eventRepository.findById(id)
            .map(eventDocument -> {
                eventDocument.setStatus(status);
                return eventDocument;
            })
            .flatMap(event -> Mono.defer(() -> eventRepository.save(eventDocument)
                    .retryWhen(Retry.backoff(MAX_ATTEMPTS, Duration.ofSeconds(2))
                            .filter(t -> t instanceof OptimisticLockingFailureException))))
            .subscribe();
}

推荐阅读