Skip to content

CAMEL-25760: camel-alibaba-oss - skip a listed object that cannot be got instead of failing the poll - #28075

Merged
davsclaus merged 2 commits into
apache:mainfrom
allthingssecurity:camel-alibaba-oss-skip-object-that-cannot-be-got
Oct 19, 2026
Merged

davsclaus merged 2 commits into
apache:mainfrom
allthingssecurity:camel-alibaba-oss-skip-object-that-cannot-be-got

Conversation

@allthingssecurity

@allthingssecurity allthingssecurity commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor

Description

CAMEL-25760

The OSS consumer lists one page of the bucket and gets every listed object. An object that no longer exists is skipped (CAMEL-25551); any other failure of a get was rethrown, so the whole poll failed, and the continuation token was only moved on after the batch was processed. The next poll therefore listed the same page again. One object whose get always fails (access denied for that object, an Archive or Cold Archive object that is not restored, a disabled KMS key) blocked every other object of its page and all the following pages; with a bucket that fits in one page the consumer consumed nothing, until someone removed or restored the object.

This change does what camel-aws2-s3 does since CAMEL-25558:

  • a failed get of one listed object is collected, the object is skipped for this poll and reported to the consumer's exception handler with its key, and the other listed objects are consumed;
  • the poll still fails (with the first failure) when none of the listed objects could be got, as for expired credentials or no permission to get objects, so the error handling and the backoff of the scheduled consumer apply;
  • the continuation token is taken from the listing before the objects are got, as camel-aws2-s3 and camel-huaweicloud-obs do with their marker, so a page whose objects cannot be got does not hold the consumer back. Its objects are listed again when the listing starts over.

An object deleted after the listing is still skipped at DEBUG. The behaviour change (a skipped object is reported at every poll that lists it; a failed poll no longer repeats the same page) is in the 4.24 upgrade guide.

Tests:

  • New OSSConsumerObjectThatCannotBeGotTest (3 tests) with a fake bucket that lists its keys in order, maxKeys at a time with a continuation token, and answers the get of a forbidden object with 403. Without the fix objectThatCannotBeGotDoesNotBlockTheOtherObjects (a.txt, forbidden b.txt, c.txt) and pageOfObjectsThatCannotBeGotDoesNotBlockTheNextPage (maxMessagesPerPoll=1, forbidden a.txt) receive no object at all. pollFailsWhenNoListedObjectCanBeGot passes with and without the fix; it is there because the fix must not swallow that case.
  • After the review, the checks of the objects left in the bucket wait for them (bd114c4): with deleteAfterRead=true an object is deleted when its exchange completes, which is after it reached mock:result. The test class passed 3 runs in a row.
  • camel-alibaba-oss unit tests: 22 run, 0 failures (formatter and import sort run in the same build).
  • Not run: against a real OSS bucket. The status codes for forbidden and archived objects are from the OSS documentation.

How it was found: comparing the sibling object-store consumers (camel-aws2-s3 after CAMEL-25558, camel-huaweicloud-obs, camel-alibaba-oss) on the same listing, get and commit steps. camel-huaweicloud-obs also fails the poll for one object, but moves its marker on, so it stops for good only when the bucket fits in one page (fixed separately). camel-alibaba-oss also keeps its listing position, so it stops for good whatever the size of the bucket.

Not changed here: camel-minio (a failed get in MinioConsumer.processBatch stops the rest of the batch and fails the poll) and camel-google-storage (GoogleCloudStorageConsumer.addExchange rethrows, and the poll fails) have the same kind of defect; they are follow-ups.

Target

  • I checked that the commit is targeting the correct branch (Camel 4 uses the main branch)

Tracking

  • If this is a large change, bug fix, or code improvement, I checked there is a JIRA issue filed for the change (usually before you start working on it).

Apache Camel coding standards and style

  • I checked that each commit in the pull request has a meaningful subject line and body.
  • I have run mvn clean install -DskipTests locally from root folder and I have committed all auto-generated changes.
    (I built and tested camel-alibaba-oss, including the formatter and import-sort plugins. I did not run the full root build.)

AI-assisted contributions

  • If this PR includes AI-generated code, commits have proper co-authorship attribution (e.g., Co-authored-by trailers) and the PR description identifies the AI tool used.
    This PR was prepared with Claude Code (Claude Opus 5.5). The commit carries a Co-Authored-By trailer.

Claude Code on behalf of allthingssecurity

🤖 Generated with Claude Code

…got instead of failing the poll

The consumer gets every object of a listed page. An object that no longer
exists was skipped, but any other failure of a get (access denied for that
object, an archived object that is not restored) failed the whole poll, and the
continuation token was only moved on after the batch was processed, so the next
poll listed the same page again. One such object kept the consumer from
consuming any object of its page and of the following pages, for good.

As camel-aws2-s3 does since CAMEL-25558: a failed get of one listed object is
reported to the exception handler of the consumer with its key and the object
is skipped for this poll, the other objects are consumed, and the poll fails
only when none of the listed objects could be got. The continuation token is
taken from the listing before the objects are got, as camel-aws2-s3 and
camel-huaweicloud-obs do with their marker, so a page whose objects cannot be
got does not hold the consumer back.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

🌟 Thank you for your contribution to the Apache Camel project! 🌟
🤖 CI automation will test this PR automatically.

🐫 Apache Camel Committers, please review the following items:

  • First-time contributors require MANUAL approval for the GitHub Actions to run
  • You can use the command /component-test (camel-)component-name1 (camel-)component-name2.. to request a test from the test bot although they are normally detected and executed by CI.
  • You can label PRs using skip-tests and test-dependents to fine-tune the checks executed by this PR.
  • Build and test logs are available in the summary page. Only Apache Camel committers have access to the summary.

⚠️ Be careful when sharing logs. Review their contents before sharing them publicly.

@davsclaus davsclaus left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this, and for keeping it so close to the camel-aws2-s3 fix from CAMEL-25558: the collect-then-decide loop, the "none could be got, fail the poll" rule and the exception-handler message all match, so the three object-store consumers now act the same way.

What I checked:

  • Moving the continuation token on before the gets is the right call here. Before, the token only moved after a successful batch, so one bad object pinned the consumer to its page. The upgrade-guide entry covers that the next page is read even after a failed poll.
  • The in-progress and not-found skips (CAMEL-25551) are unchanged, and releaseNotProcessed still runs when the poll fails.
  • The tests use AssertJ like the rest of the module, Awaitility instead of sleeps, and the 3 cases cover the skip, the next page, and the poll that must still fail.

Minor points, none blocking:

  • An object that stays forbidden is reported at WARN with a stack trace at every poll that lists it (every 500 ms by default in a bucket that fits in one page). That is the same as camel-aws2-s3 and the upgrade guide says so, so I'm fine with it. A user who finds it noisy can set an exceptionHandler.
  • A page whose other objects are all still in flight (or deleted) counts as "none could be got", so one forbidden object on that page fails the poll. That matches S3, and because the token has already moved on, it doesn't block anything.
  • Could you file the camel-minio and camel-google-storage follow-ups you mention in JIRA, so they don't get lost?

CI was just approved and is still running. Approving on the code, assuming CI comes back green.

Claude Code on behalf of Claus Ibsen. This review was generated by an AI agent and may contain inaccuracies. Please verify all suggestions before applying.

@github-actions

github-actions Bot commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor

🧪 CI tested the following changed modules:

  • components/camel-alibaba/camel-alibaba-oss
  • docs

🔁 1 test passed only after a retry on JDK 17 (1 retried attempt)

Recovered flaky tests on JDK 17 (1)
Module Test Failed attempts First failure
dsl/camel-jbang/camel-jbang-plugin-tui LaunchManagerOutcomeTest.startedWhenTheStatusFileSaysSo 1 Failed to close extension context

ℹ️ These tests did not fail the build. Surefire retried them and they passed.
Retries are enabled project-wide by surefire.rerunFailingTestsCount in parent/pom.xml.


🔬 Scalpel shadow comparison — Scalpel: 8 of 707 tested, 26 compile-only — current: 8 all tested

Maveniverse Scalpel detected 8 affected modules (current approach: 8).

Skip-tests mode would test 8 modules (2 direct + 7 downstream), skip tests for 26 (generated code, meta-modules)

Modules Scalpel would test (8)
  • camel-alibaba-oss ← components/camel-alibaba/camel-alibaba-oss/src/main/java/org/apache/camel/component/alibaba/oss/OSSConsumer.java, components/camel-alibaba/camel-alibaba-oss/src/test/java/org/apache/camel/component/alibaba/oss/OSSConsumerObjectThatCannotBeGotTest.java
  • camel-jbang-mcp ← downstream of org.apache.camel:camel-catalog
  • camel-jbang-plugin-mcp ← downstream of org.apache.camel:camel-jbang-core
  • camel-jbang-plugin-tui ← downstream of org.apache.camel:camel-catalog
  • camel-jbang-plugin-validate ← downstream of org.apache.camel:camel-yaml-dsl-validator
  • camel-launcher-container ← downstream of org.apache.camel:camel-launcher
  • camel-yaml-dsl-validator ← downstream of org.apache.camel:camel-catalog
  • camel-yaml-dsl-validator-maven-plugin ← downstream of org.apache.camel:camel-yaml-dsl-validator
Modules with tests skipped (26)
  • apache-camel
  • camel-allcomponents
  • camel-catalog
  • camel-catalog-console
  • camel-catalog-maven
  • camel-catalog-suggest
  • camel-componentdsl
  • camel-endpointdsl
  • camel-endpointdsl-support
  • camel-itest
  • camel-jbang-core
  • camel-jbang-it
  • camel-jbang-main
  • camel-jbang-plugin-edit
  • camel-jbang-plugin-generate
  • camel-jbang-plugin-kubernetes
  • camel-jbang-plugin-test
  • camel-kamelet-main
  • camel-launcher
  • camel-report-maven-plugin
  • camel-route-parser
  • camel-yaml-dsl
  • camel-yaml-dsl-deserializers
  • camel-yaml-dsl-maven-plugin
  • coverage
  • dummy-component

ℹ️ Shadow mode — Scalpel observes but does not affect test execution. Learn more

All tested modules (35 modules, 6m 8s total)

Total reactor time: 6m 8s

Module Duration Status
Camel :: Launcher 51.1s SUCCESS
Camel :: JBang :: MCP 44.6s SUCCESS
Camel :: JBang :: Plugin :: Validate 28.9s SUCCESS
Camel :: Alibaba Cloud :: OSS 26.3s SUCCESS
Camel :: YAML DSL 26.0s SUCCESS
Camel :: Catalog :: Camel Catalog 25.8s SUCCESS
Camel :: YAML DSL :: Validator 24.5s SUCCESS
Camel :: Component DSL 19.2s SUCCESS
Camel :: JBang :: Plugin :: Testing 17.6s SUCCESS
Camel :: Docs 17.2s SUCCESS
Camel :: JBang :: Plugin :: Kubernetes 14.4s SUCCESS
Camel :: Kamelet Main 12.2s SUCCESS
Camel :: Catalog :: Camel Report Maven Plugin 9.7s SUCCESS
Camel :: YAML DSL :: Deserializers 8.6s SUCCESS
Camel :: Catalog :: Camel Route Parser 8.6s SUCCESS
Camel :: YAML DSL :: Validator Maven Plugin 5.8s SUCCESS
Camel :: All Components Sync point 5.3s SUCCESS
Camel :: YAML DSL :: Maven Plugins 3.8s SUCCESS
Camel :: Catalog :: Maven 3.3s SUCCESS
Camel :: Catalog :: Suggest (deprecated) 2.8s SUCCESS
Camel :: Assembly 1.9s SUCCESS
Camel :: JBang :: Plugin :: Edit 1.6s SUCCESS
Camel :: Catalog :: Dummy Component 1.4s SUCCESS
Camel :: JBang :: Main 1.2s SUCCESS
Camel :: JBang :: Plugin :: Generate 1.2s SUCCESS
Camel :: Coverage 1.1s SUCCESS
Camel :: Catalog :: Console 1.0s SUCCESS
Camel :: JBang :: Plugin :: MCP 0.9s SUCCESS
Camel :: JBang :: Integration tests 0.9s SUCCESS
Camel :: Endpoint DSL :: Support 0.7s SUCCESS
Camel :: Launcher :: Container 0.7s SUCCESS
Camel :: Endpoint DSL n/a
Camel :: Integration Tests n/a
Camel :: JBang :: Core n/a
Camel :: JBang :: Plugin :: TUI n/a

Top 20 slowest modules:

  • Camel :: Launcher (51.1s)
  • Camel :: JBang :: MCP (44.6s)
  • Camel :: JBang :: Plugin :: Validate (28.9s)
  • Camel :: Alibaba Cloud :: OSS (26.3s)
  • Camel :: YAML DSL (26.0s)
  • Camel :: Catalog :: Camel Catalog (25.8s)
  • Camel :: YAML DSL :: Validator (24.5s)
  • Camel :: Component DSL (19.2s)
  • Camel :: JBang :: Plugin :: Testing (17.6s)
  • Camel :: Docs (17.2s)
  • Camel :: JBang :: Plugin :: Kubernetes (14.4s)
  • Camel :: Kamelet Main (12.2s)
  • Camel :: Catalog :: Camel Report Maven Plugin (9.7s)
  • Camel :: YAML DSL :: Deserializers (8.6s)
  • Camel :: Catalog :: Camel Route Parser (8.6s)
  • Camel :: YAML DSL :: Validator Maven Plugin (5.8s)
  • Camel :: All Components Sync point (5.3s)
  • Camel :: YAML DSL :: Maven Plugins (3.8s)
  • Camel :: Catalog :: Maven (3.3s)
  • Camel :: Catalog :: Suggest (deprecated) (2.8s)

⚙️ View full build and test results

@davsclaus

Copy link
Copy Markdown
Contributor

Closing and reopening to re-run CI against main: the CatalogSamplesTest.callingAServiceIsTheHttpComponentNotEnrich failure in camel-jbang-core came from main and is fixed there (bbd6f75). Nothing to change in this PR.

Claude Code on behalf of Claus Ibsen

@davsclaus davsclaus closed this Oct 19, 2026
@davsclaus davsclaus reopened this Oct 19, 2026

@davsclaus davsclaus left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One follow-up on the test, to keep it from becoming flaky: see the two suggestions below.

Claude Code on behalf of Claus Ibsen. This review was generated by an AI agent and may contain inaccuracies. Please verify all suggestions before applying.

@davsclaus davsclaus closed this Oct 19, 2026
@davsclaus davsclaus reopened this Oct 19, 2026
…test

As suggested in the review, the object is deleted when the exchange completes,
after it reached mock:result, so the test waits for the bucket content.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@gnodet-bot gnodet-bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. No issues found.

Correct port of the CAMEL-25558 collect-then-decide pattern from camel-aws2-s3. The anyGot/failures logic traces correctly through all edge cases (in-progress skips, deleted objects, forbidden objects, empty-page); continuation token advancement before the get loop is sound and well-documented; tests 1 and 2 would definitively fail without the fix (old code throws on the first 403 and never processes the remaining objects; test 2's consumer gets stuck on the forbidden-only page with no token advancement). No gaps vs davsclaus's review found.

This review was generated by an AI agent, Hermès on behalf of @gnodet.

@davsclaus davsclaus left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @allthingssecurity. bd114c4 waits for the bucket with Awaitility (atMost(20, SECONDS)) in both deleteAfterRead tests, so the check no longer races the delete that runs when the exchange completes. objects is a ConcurrentSkipListSet, so reading it from the test thread while the consumer deletes is safe. The third test expects no deletes, so it has no such race. The assertions stay AssertJ, as in the rest of the class. I resolved my two threads.

Claude Code on behalf of Claus Ibsen

@davsclaus davsclaus added this to the 4.24.0 milestone Oct 19, 2026
@davsclaus davsclaus added the bug Something isn't working label Oct 19, 2026
@davsclaus
davsclaus merged commit a2a592c into apache:main Oct 19, 2026
7 checks passed
@allthingssecurity
allthingssecurity deleted the camel-alibaba-oss-skip-object-that-cannot-be-got branch October 19, 2026 14:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working components docs

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants