Hi Pau Oh that is a tough use-case you have and some great analysis and details you provide.
Error handler is hard and Camel has a lot of features in this matter and it can be tricky. However I do think you have shown a reason for us to allow the on redelivery processor to control whether the redelivery should be executed or not via the route stop marker. https://issues.apache.org/jira/browse/CAMEL-17660 On Wed, Jan 19, 2022 at 11:28 AM Pau Pachès <pav...@gmail.com> wrote: > > 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 -- Claus Ibsen ----------------- http://davsclaus.com @davsclaus Camel in Action 2: https://www.manning.com/ibsen2