Uploaded image for project: 'Red Hat build of Apache Camel'
  1. Red Hat build of Apache Camel
  2. RHBAC-310

camel-google-pubsub: Add max delivery attempts awareness to avoid infinite redelivery loops

XMLWordPrintable

    • Icon: Feature Feature
    • Resolution: Unresolved
    • Icon: Major Major
    • None
    • 4.14.GA
    • Camel for Quarkus
    • None
    • False
    • Hide

      None

      Show
      None
    • False

      Subscription example configuration:

      gcloud pubsub subscriptions create publisher-subscription \
        --topic=publisher-topic \
        --ack-deadline=10 \
        --dead-letter-topic=publisher-topic-dlq \
        --max-delivery-attempts=5 \
        --min-retry-delay=5s \
        --max-retry-delay=15s

      The camel-google-pubsub component does not expose or act upon the subscription-level maxDeliveryAttempts setting from the dead-letter policy. When a subscription is configured with a short retry window (--min-retry-delay=5s, --max-retry-delay=15s), the consumer enters an infinite redelivery loop because it has no mechanism to compare the current delivery attempt against the configured maximum. The component should be able to avoid this infinite loop when using a low window delays. 

      Increasing --min-retry-delay to 30s and --max-retry-delay to 60s alleviates the symptom but does not address the root cause, the component lacks delivery attempt control.

      In general the library should retrieve the  maxDeliveryAttempts from the subscription dead-letter policy at startup, expose the current delivery attempt and optionally enforce the max delivery control, when the current attempt reaches maxDeliveryAttempts, the component could automatically NACK the message (allowing Pub/Sub to route it to the DLQ) instead of continuing to process it.

      WORKAROUND:

       

      //Add these imports
      import com.google.cloud.pubsub.v1.SubscriptionAdminClient;
      import com.google.pubsub.v1.DeadLetterPolicy;
      import com.google.pubsub.v1.Subscription;
      import com.google.pubsub.v1.SubscriptionName;
      ...
      public class PubSubRoute extends RouteBuilder {
      ...
        @Override
        public void configure() throws Exception {
      ...
          try (SubscriptionAdminClient client = SubscriptionAdminClient.create()) {
              SubscriptionName subName = SubscriptionName.of(projectId, subscriptionId);
              Subscription sub = client.getSubscription(subName);
              DeadLetterPolicy dlp = sub.getDeadLetterPolicy();
              int maxAttempts = dlp.getMaxDeliveryAttempts();
              log.info("maxDeliveryAttempts={}", maxAttempts);
          }
      ...

       

      The above will capture the property correctly:

       

      2026-03-04 10:55:47,750 INFO  [demo.PubSubRoute] (Quarkus Main Thread) maxDeliveryAttempts=5

       

      Then you can capture the current attempt:

      ...
                      Object rawAttrs =
                              exchange.getIn().getHeader(GooglePubsubConstants.ATTRIBUTES);
                      Map<String, String> attrs = new HashMap<>();
                      if (rawAttrs instanceof Map<?, ?> map) {
                          for (Map.Entry<?, ?> e : map.entrySet()) {
                              if (e.getKey() instanceof String && e.getValue() instanceof String) {
                                  attrs.put((String) e.getKey(), (String) e.getValue());
                              }
                          }
                      }
                      int attempt = Integer.parseInt(
                              attrs.getOrDefault("googclient_deliveryattempt", "1")
                      );
      ...
      

       

      And apply the max delivery control in your camel solution.
       

      if (attempt >= maxAttempts) { 
      thrownewRuntimeException("Max delivery attempts exceeded"); 
      }

       

              Unassigned Unassigned
              emunoz@redhat.com Elkin Dario Munoz Duarte
              Votes:
              0 Vote for this issue
              Watchers:
              2 Start watching this issue

                Created:
                Updated: