This is an automated email from the ASF dual-hosted git repository.

oscerd pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git


The following commit(s) were added to refs/heads/main by this push:
     new 9b26b811fd27 CAMEL-24491: camel-ibm-cos - make consumer in-progress 
deduplication effective (#25740)
9b26b811fd27 is described below

commit 9b26b811fd2798bda130d441538cd339d8ccf4e2
Author: Andrea Cosentino <[email protected]>
AuthorDate: Wed Aug 26 11:52:44 2026 +0200

    CAMEL-24491: camel-ibm-cos - make consumer in-progress deduplication 
effective (#25740)
    
    * CAMEL-24491: camel-ibm-cos - make consumer in-progress deduplication 
effective
    
    The IBM COS consumer's in-progress deduplication never worked: 
createExchanges()
    only checked getInProgressRepository().contains(key) without ever adding the
    key, the MemoryIdempotentRepository was started only after doStart()'s early
    returns (so never in the normal consuming case), and 
processCommit/processRollback
    never removed the key. As a result overlapping polls could re-deliver an 
object
    still being processed when deleteAfterRead/moveAfterRead were off.
    
    Mirror the camel-aws2-s3 consumer this module was copied from: use
    getInProgressRepository().add(key) as the atomic guard (skip when it returns
    false), remove the key in processCommit (finally) and processRollback via a
    null-safe helper, and start the in-progress repository up front in doStart()
    before any early return.
    
    Co-Authored-By: Claude Opus 4.8 <[email protected]>
    Signed-off-by: Andrea Cosentino <[email protected]>
    
    * CAMEL-24491: release the in-progress key when the object fetch or 
exchange creation fails
    
    Addresses review feedback: if getObject/createExchange throws after add(key)
    has claimed the in-progress key, no Synchronization is attached to remove 
it, so
    the object would be left permanently unconsumable. Release the key (and 
skip the
    object for this poll) so a transient failure does not silently block the 
object.
    
    Co-Authored-By: Claude Opus 4.8 <[email protected]>
    Signed-off-by: Andrea Cosentino <[email protected]>
    
    ---------
    
    Signed-off-by: Andrea Cosentino <[email protected]>
    Co-authored-by: Claude Opus 4.8 <[email protected]>
---
 .../camel/component/ibm/cos/IBMCOSConsumer.java    | 27 ++++++++++++++++++----
 .../camel/component/ibm/cos/IBMCOSEndpoint.java    |  5 ++--
 2 files changed, 25 insertions(+), 7 deletions(-)

diff --git 
a/components/camel-ibm/camel-ibm-cos/src/main/java/org/apache/camel/component/ibm/cos/IBMCOSConsumer.java
 
b/components/camel-ibm/camel-ibm-cos/src/main/java/org/apache/camel/component/ibm/cos/IBMCOSConsumer.java
index 233723ac43f7..66de7917f054 100644
--- 
a/components/camel-ibm/camel-ibm-cos/src/main/java/org/apache/camel/component/ibm/cos/IBMCOSConsumer.java
+++ 
b/components/camel-ibm/camel-ibm-cos/src/main/java/org/apache/camel/component/ibm/cos/IBMCOSConsumer.java
@@ -160,15 +160,23 @@ public class IBMCOSConsumer extends 
ScheduledBatchPollingConsumer {
             }
 
             if (getEndpoint().getInProgressRepository() != null
-                    && 
getEndpoint().getInProgressRepository().contains(s3ObjectSummary.getKey())) {
+                    && 
!getEndpoint().getInProgressRepository().add(s3ObjectSummary.getKey())) {
                 LOG.trace("Object {} is already in progress", 
s3ObjectSummary.getKey());
                 continue;
             }
 
-            S3Object s3Object = getCosClient().getObject(
-                    new GetObjectRequest(s3ObjectSummary.getBucketName(), 
s3ObjectSummary.getKey()));
-            Exchange exchange = createExchange(s3Object, 
s3ObjectSummary.getKey());
-            exchanges.add(exchange);
+            try {
+                S3Object s3Object = getCosClient().getObject(
+                        new GetObjectRequest(s3ObjectSummary.getBucketName(), 
s3ObjectSummary.getKey()));
+                Exchange exchange = createExchange(s3Object, 
s3ObjectSummary.getKey());
+                exchanges.add(exchange);
+            } catch (Exception e) {
+                // Fetching the object or creating the exchange failed after 
we claimed the in-progress key;
+                // release it so the object is not left permanently 
unconsumable, and skip it for this poll.
+                LOG.warn("Error fetching object {} from bucket {}: {}. 
Skipping it for this poll.",
+                        s3ObjectSummary.getKey(), 
s3ObjectSummary.getBucketName(), e.getMessage());
+                removeInProgress(s3ObjectSummary.getKey());
+            }
         }
 
         return exchanges;
@@ -246,11 +254,20 @@ public class IBMCOSConsumer extends 
ScheduledBatchPollingConsumer {
             }
         } catch (Exception e) {
             LOG.warn("Error during post processing of object {} from bucket 
{}: {}", key, bucketName, e.getMessage());
+        } finally {
+            removeInProgress(key);
         }
     }
 
     protected void processRollback(String key) {
         LOG.trace("Processing failed for object with key {}", key);
+        removeInProgress(key);
+    }
+
+    private void removeInProgress(String key) {
+        if (getEndpoint().getInProgressRepository() != null) {
+            getEndpoint().getInProgressRepository().remove(key);
+        }
     }
 
     private void copyObject(String bucketName, String key) {
diff --git 
a/components/camel-ibm/camel-ibm-cos/src/main/java/org/apache/camel/component/ibm/cos/IBMCOSEndpoint.java
 
b/components/camel-ibm/camel-ibm-cos/src/main/java/org/apache/camel/component/ibm/cos/IBMCOSEndpoint.java
index 63d9d5b5478b..dcbafcfd3dc9 100644
--- 
a/components/camel-ibm/camel-ibm-cos/src/main/java/org/apache/camel/component/ibm/cos/IBMCOSEndpoint.java
+++ 
b/components/camel-ibm/camel-ibm-cos/src/main/java/org/apache/camel/component/ibm/cos/IBMCOSEndpoint.java
@@ -115,6 +115,9 @@ public class IBMCOSEndpoint extends ScheduledPollEndpoint 
implements EndpointSer
     protected void doStart() throws Exception {
         super.doStart();
 
+        // Start the in-progress repository up front so consumer deduplication 
works even when doStart returns early
+        ServiceHelper.startService(inProgressRepository);
+
         cosClient = configuration.getCosClient() != null
                 ? configuration.getCosClient() : createCosClient();
 
@@ -146,8 +149,6 @@ public class IBMCOSEndpoint extends ScheduledPollEndpoint 
implements EndpointSer
             cosClient.createBucket(bucketName);
             LOG.trace("Bucket created");
         }
-
-        ServiceHelper.startService(inProgressRepository);
     }
 
     @Override

Reply via email to