Hi,
I posted this to stack overflow but no answers and very few readings.
I have a use case in which a business task sends an email through Camel.
There are three redeliveries separated by 60 seconds.
I attempt to send the email once, but let's assume the server is not
answering and while the first redelivery is waiting to happen, I
cancel the task and switch on the SMTP server.
What I have seen is that the redelivery, which is successful since the
SMTP server is already up, is hard to stop. But the exchange should
not be delivered as the business task has been cancelled.
My route is as follows:
from(fromUri)
                .onException(Exception.class)
                .retryWhile(new Predicate() {
                    @Override
                    public boolean matches(Exchange exchange) {

                        if (checkForCancellation(exchange,
"retryWhile-matches")) {
                            return false;
                        }
                        int maxCount = retrySettings.getCount();
                        var counter =
exchange.getIn().getHeader(Exchange.REDELIVERY_COUNTER,
Integer.class);
                        if (counter > maxCount) {
                            return false;
                        }
                        ...
                    }
                })
                .retryAttemptedLogLevel(LoggingLevel.INFO)
                .logExhaustedMessageHistory(false).logStackTrace(false)
                .logRetryAttempted(true)
                .redeliveryDelay(retrySettings.getInterval() * 1000)
                .onRedelivery(new FlowAlreadyCancelledProcessor(tenant, domain))
                .continued(retrySettings.getAction() ==
RetrySettings.RetryFailureAction.Ignore)
                .end()
                .choice()
                .when(exchange -> (!checkForCancellation(exchange, "in
choice")))
                .toD(outputUri)
                .otherwise()
                .stop()
                .end()
                .setId(fromUri);

Apparently the retry is scheduled and the retryWhile is not visited,
and it sort of makes sense since there is no exception at the first
retry, since the SMTP server is up at the time.
Which is why I added the
.choice()
                .when(exchange -> (!checkForCancellation(exchange, "in
choice")))
                .toD(outputUri)
                .otherwise()
                .stop()
                .end()

block, but this does not seem to be executed either. The retry is
scheduled and looking at the RedeliveryErrorHandler.java I see that
the only thing that is executed is the on-redelivery processor. So I
thought that would solve the problem, I wrote one:
 public void process(Exchange exchange) throws Exception {
        logger.debug("Entering {} process", this.getClass().getName());

        if (org.apache.commons.lang3.StringUtils.isNotBlank(flowId)) {
            Optional<Flow> flowOptional =
RuntimeService.getInstance().getFlow(UUID.fromString(flowId), tenant,
domain);
            if (flowOptional.isPresent() &&
flowOptional.get().getStatus() == FlowStatus.canceled) {
                logger.debug("Should not redeliver since flow {} is
canceled", flowId);
                exchange.setException(new MyException("Flow already canceled"));
                exchange.setRouteStop(true);
                return;
            }
        }
        logger.debug("Redelivery will take place as flow is not canceled");
    }

I thought setting an exception and calling setRouteStop would be
enough, but the exchange is not cancelled and the retry is still
executed.
The RedeliveryErrorHandler knows the concept of cancelling a task, the
comment "a task has been cancelled" appears three times, but I cannot
succeed in making that code be executed. Any ideas?

Thanks,

pau

Reply via email to