Skip to content

[backport camel-4.22.x] CAMEL-25781: camel-azure-eventhubs - an event that completes when the checkpoint timer of its window has run is checkpointed by the next timer - #28207

Merged
gnodet merged 2 commits into
apache:camel-4.22.xfrom
gnodet:backport/28135-to-camel-4.22.x
Oct 21, 2026

Conversation

@gnodet

@gnodet gnodet commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

Backport of #28135

Cherry-pick of 727cab8 to camel-4.22.x.
Conflicts resolved automatically by backport bot agent.

Also brings the consumer part of CAMEL-25683 (#27922) to camel-4.22.x:

  • Change batch-size check from == to >= (a failed timeout checkpoint adds its count back, so the count can pass the batch size)
  • Remove cancelled task from checkpointTasksByPartition and scheduledTasksByPartition after a checkpoint by batch size
  • Add EventHubsConsumerCheckpointAfterBatchSizeTest

The upgrade guide note is placed in a new "Upgrading from 4.22.2 to 4.22.3" section.
The same note has been added to main's upgrade guide in #28238.

… that completes when the checkpoint timer of its window has run is checkpointed by the next timer
@gnodet gnodet added the backport indicate that a Pull request is a backport from a fix from the main branch label Oct 21, 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.

Thanks Guillaume. This backports the CAMEL-25781 fix to camel-4.22.x. The CAMEL-25781 part matches #28135, and EventHubsConsumerCheckpointWindowTest is identical. But camel-4.22.x does not have CAMEL-25683 (#27922, main only), and the conflict resolution brought in half of it. EventHubsCheckpointUpdaterTask.run() now takes the count with getAndSet(0) and adds it back when the checkpoint fails. processCommit still checks cnt == getConfiguration().getCheckpointBatchSize().

  1. Blocking. Because of the add back, the count can jump past the batch size after a failed timer checkpoint. For example, with a batch size of 500, 250 counted plus 300 added back gives 550. After that, == never matches, so no checkpoint by batch size happens until the next timer resets the count. Main uses >= for exactly this reason. Please bring the consumer part of CAMEL-25683 too:

    • change the check to >=
    • remove the cancelled task from checkpointTasksByPartition and scheduledTasksByPartition. With the isDone() check this is redundant, but it keeps the file the same as main.
    • add EventHubsConsumerCheckpointAfterBatchSizeTest

    CAMEL-25683 is a bug fix for events that are delivered again after a restart, so backporting it fits the backport policy. Please also mention it in the PR description and add 4.22.3 to its fix versions.

  2. Not blocking. The upgrade note sits under "Upgrading Camel 4.21 to 4.22". 4.22.2 is already tagged, so this fix ships in 4.22.3 and needs a new "Upgrading from 4.22.2 to 4.22.3" section. The same entry also has to go into camel-4x-upgrade-guide-4_22.adoc on main, which already has that section.

Leaving out the DST test change from #28135 is correct, because camel-test-dst is not on 4.22.x. CI is still running.

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

Comment thread docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_22.adoc Outdated
@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.

@github-actions

github-actions Bot commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

🧪 CI tested the following changed modules:

  • components/camel-azure/camel-azure-eventhubs
  • docs

🔬 Scalpel shadow comparison — Scalpel: 10 tested, 28 compile-only — current: 9 all tested

Maveniverse Scalpel detected 38 affected modules (current approach: 9).

⚠️ Modules only in Scalpel (29)
  • apache-camel
  • camel-allcomponents
  • camel-catalog
  • camel-catalog-console
  • camel-catalog-lucene
  • camel-catalog-maven
  • camel-catalog-suggest
  • camel-componentdsl
  • camel-csimple-maven-plugin
  • 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
  • docs
  • dummy-component

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

Modules Scalpel would test (10)
  • camel-azure-eventhubs
  • camel-jbang-mcp
  • camel-jbang-plugin-mcp
  • camel-jbang-plugin-route-parser
  • camel-jbang-plugin-tui
  • camel-jbang-plugin-validate
  • camel-launcher-container
  • camel-yaml-dsl-validator
  • camel-yaml-dsl-validator-maven-plugin
  • docs
Modules with tests skipped (28)
  • apache-camel
  • camel-allcomponents
  • camel-catalog
  • camel-catalog-console
  • camel-catalog-lucene
  • camel-catalog-maven
  • camel-catalog-suggest
  • camel-componentdsl
  • camel-csimple-maven-plugin
  • 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 (38 modules)
  • Camel :: All Components Sync point
  • Camel :: Assembly
  • Camel :: Azure :: Event Hubs
  • Camel :: Catalog :: CSimple Maven Plugin (deprecated)
  • Camel :: Catalog :: Camel Catalog
  • Camel :: Catalog :: Camel Report Maven Plugin
  • Camel :: Catalog :: Camel Route Parser
  • Camel :: Catalog :: Console
  • Camel :: Catalog :: Dummy Component
  • Camel :: Catalog :: Lucene (deprecated)
  • Camel :: Catalog :: Maven
  • Camel :: Catalog :: Suggest
  • Camel :: Component DSL
  • Camel :: Coverage
  • Camel :: Docs
  • Camel :: Endpoint DSL
  • Camel :: Endpoint DSL :: Support
  • Camel :: Integration Tests
  • Camel :: JBang :: Core
  • Camel :: JBang :: Integration tests
  • Camel :: JBang :: MCP
  • Camel :: JBang :: Main
  • Camel :: JBang :: Plugin :: Edit
  • Camel :: JBang :: Plugin :: Generate
  • Camel :: JBang :: Plugin :: Kubernetes
  • Camel :: JBang :: Plugin :: MCP
  • Camel :: JBang :: Plugin :: Route Parser
  • Camel :: JBang :: Plugin :: TUI
  • Camel :: JBang :: Plugin :: Testing
  • Camel :: JBang :: Plugin :: Validate
  • Camel :: Kamelet Main
  • Camel :: Launcher
  • Camel :: Launcher :: Container
  • Camel :: YAML DSL
  • Camel :: YAML DSL :: Deserializers
  • Camel :: YAML DSL :: Maven Plugins
  • Camel :: YAML DSL :: Validator
  • Camel :: YAML DSL :: Validator Maven Plugin

⚙️ View full build and test results

@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.

This backport introduces two issues that need to be fixed before it can be merged.

1. Missing == → >= fix from CAMEL-25683

This cherry-pick adds the processedEvents.addAndGet(processed) error-recovery path in EventHubsCheckpointUpdaterTask.run(), which is correct. However, the batch-size check in EventHubsConsumer.processCommit() still uses cnt == (line 253 on the PR branch) rather than cnt >= as on main (line 254).

The == vs >= gap was already fixed on main by CAMEL-25683 (commit 83aaa80) with the comment "a failed timeout checkpoint adds its count back, so the count can pass the batch size". When the error-recovery path does addAndGet(processed), the counter can overshoot checkpointBatchSize, making the == condition permanently false and silently disabling batch-size checkpoints. This backport needs the same == → >= fix from CAMEL-25683.

2. Upgrade guide placed under wrong version section

The new upgrade note is added as a === subsection under == Upgrading Camel 4.21 to 4.22 (the general 4.22 section). Since 4.22.2 is already tagged, this fix ships in 4.22.3. The established convention in this file is per-patch-level sections at the top (e.g. == Upgrading from 4.22.0 to 4.22.1 at line 14). A new == Upgrading from 4.22.2 to 4.22.3 section should be added at the top of the file instead.

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

Comment thread docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_22.adoc Outdated

@oscerd oscerd 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.

TL;DR

The CAMEL-25781 part matches #28135 and CI is green; the open point from @davsclaus (the half-imported CAMEL-25683: cnt == at EventHubsConsumer.java:253 next to the new add-back at EventHubsCheckpointUpdaterTask.java:88) is still unchanged at 7d65de0, and I have one more reason for the map removal he asked for.

Blockers

  • None new from my side; the earlier "changes requested" items (>=, removal of the cancelled task from both maps, EventHubsConsumerCheckpointAfterBatchSizeTest, the 4.22.2 → 4.22.3 guide section, the same note on main's 4_22 guide) are all still open at this head.

Other findings: 1 (non-blocking)

One more reason for that map removal, beyond keeping the file equal to main. With isDone() replacing isExpired(), a timer that scheduledTask.cancel(false) stops before it starts never runs. So on this branch, checkpointTask.cancel() (EventHubsConsumer.java:258) is the only thing that marks the window done after a checkpoint by batch size. If that line were ever dropped or moved, the next events of the partition would keep joining a task that never runs, and the partition would not get a timeout checkpoint again. On main, removing the task from checkpointTasksByPartition is a second guard.

From a static trace, none of the three tests in EventHubsConsumerCheckpointWindowTest would fail here without that cancel(): the mocked ScheduledFuture ignores the cancel, so timerStartedBeforeABatchSizeCheckpointDoesNotTakeTheNextWindow passes by letting the first timer checkpoint third. EventHubsConsumerCheckpointAfterBatchSizeTest#eventAfterBatchSizeCheckpointIsCheckpointedByTimeout uses a real scheduler and covers this path; it ports without pom changes (Awaitility comes from components/pom.xml), and with the earlier point applied both production files become byte-identical to main.

Reviewed with Claude Code on behalf of oscerd. This review was generated by an AI agent and may contain inaccuracies; please verify all suggestions before applying.

- Change batch-size check from == to >= (a failed timeout checkpoint
  adds its count back, so the count can pass the batch size)
- Remove cancelled task from checkpointTasksByPartition and
  scheduledTasksByPartition after a checkpoint by batch size
- Add EventHubsConsumerCheckpointAfterBatchSizeTest
- Move upgrade note to a new '4.22.2 to 4.22.3' section

@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 Guillaume, my change request is addressed. The batch-size check is now >=, the cancelled task is removed from both per-partition maps, and EventHubsConsumerCheckpointAfterBatchSizeTest is added. EventHubsConsumer, EventHubsCheckpointUpdaterTask and the two new tests are now identical to main. The upgrade note sits in a new "Upgrading from 4.22.2 to 4.22.3" section, and #28238 adds the same text to the 4_22 guide on main.

Non-blocking: CAMEL-25683 and CAMEL-25781 still need 4.22.3 in their JIRA fix versions. That can be done at merge.

LGTM, once CI is green.

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

@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.

Following up on my earlier review — both issues have been addressed.

  • == → >= fix — ✅ addressed. cnt >= getConfiguration().getCheckpointBatchSize() is now in EventHubsConsumer.processCommit() with the correct comment explaining why.
  • Upgrade guide section — ✅ addressed. A new == Upgrading from 4.22.2 to 4.22.3 top-level section is placed correctly before == Upgrading from 4.22.1 to 4.22.2.
  • Map cleanup — ✅ addressed. Both checkpointTasksByPartition.remove(partitionId) and scheduledTasksByPartition.remove(partitionId) are called after a batch-size checkpoint.
  • EventHubsConsumerCheckpointAfterBatchSizeTest — ✅ added. Five tests with a real scheduler, including batchSizeCheckpointStillWorksAfterFailedTimeoutCheckpoint which directly validates the addAndGet + >= interaction.
  • EventHubsConsumerCheckpointWindowTest — ✅ added. Three tests covering the isDone()-based window boundary logic with a mocked scheduler.

The locking design in EventHubsCheckpointUpdaterTask (shared consumer lock, done flag set atomically before getAndSet(0)) is correct: an event that completes while the timer holds the lock will see isDone() == true and start a fresh window, so the add-back in the error path cannot race with a concurrent batch-size checkpoint.

No new findings. LGTM.

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

@gnodet
gnodet merged commit c992be1 into apache:camel-4.22.x Oct 21, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backport indicate that a Pull request is a backport from a fix from the main branch components components-azure docs

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants