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