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

Reply via email to