shashank created CAMEL-25683:
--------------------------------

             Summary: camel-azure-eventhubs - after a checkpoint by 
checkpointBatchSize, the following events of the partition are not checkpointed 
by checkpointBatchTimeout, so a restart or rebalance after a burst delivers 
them again
                 Key: CAMEL-25683
                 URL: https://issues.apache.org/jira/browse/CAMEL-25683
             Project: Camel
          Issue Type: Bug
          Components: camel-azure-eventhubs
            Reporter: shashank
            Assignee: shashank


{{EventHubsConsumer.processCommit}} (lines 225-278 at main cd2ce899764e) keeps, 
per partition, a checkpoint task that a scheduler runs 
{{checkpointBatchTimeout}} after the first event of a window, and checkpoints 
at once when {{checkpointBatchSize}} events have completed. When the batch size 
is reached it cancels the scheduled future (253-255) but leaves the task in 
{{checkpointTasksByPartition}}. Until the time that task was scheduled for, 
every following event of the partition finds it not expired (234) and only sets 
its event context on it (244). The task is cancelled, so nothing checkpoints 
these events by time. The first event that completes after that time starts a 
new task, which then checkpoints all of them.

If no event of the partition completes after that time - the end of a burst - 
the events completed after the size checkpoint are not checkpointed until the 
next event arrives, which can be hours later. A restart of the application, or 
the partition moving to another consumer of the group (load balancing when 
instances are added or removed), starts from the last checkpoint and delivers 
them again: up to {{checkpointBatchSize - 1}} events per partition.

Example with the defaults (batch size 500, timeout 5000 ms): a burst of 700 
events within 5 seconds, then quiet. Events 1-500 are checkpointed by size; 
events 501-700 stay uncheckpointed until the next event of that partition. 
Before CAMEL-24198 (one task for the consumer) the same happened (4.18.x: 
{{lastTask}} / {{lastScheduledTask}}).

A second, smaller cause of the same symptom: 
{{EventHubsCheckpointUpdaterTask.run()}} (lines 43-50) resets the per-partition 
counter with {{processedEvents.set(0)}} in the completion callback of its 
checkpoint, on a reactor thread and without the consumer's lock. The counter is 
shared with the next task of the partition, so an event that completes while 
that checkpoint is being stored (the round trip to the checkpoint store) and 
starts the next window is wiped from the count; the next task then finds 0 and 
skips its checkpoint.

h3. Reproduction

New {{EventHubsConsumerCheckpointAfterBatchSizeTest}} (3 tests, the style of 
{{EventHubsConsumerPerPartitionCheckpointTest}}: mocked {{EventContext}}, 
{{processCommit}} called directly, but a real single-thread scheduler; batch 
size 2, timeout 1000 ms):
* events 1 and 2 (checkpoint by size at event 2), then event 3 and nothing 
else: event 3 must be checkpointed within 10 seconds. On main: {{Wanted but not 
invoked: eventContext.updateCheckpointAsync()}} after 10 s.
* events 1-5 (checkpoints by size at 2 and 4): event 5 must be checkpointed. On 
main: the same.
* batch size 10: event 1 is checkpointed by the timeout, whose {{Mono}} 
completes only after event 2 has completed (and started the next window): event 
2 must be checkpointed by the next timeout. On main: the same.

h3. Proposed fix

When the batch size is reached, remove the task and its future from the two 
maps after cancelling the future, so the next event of the partition starts a 
new timeout window, as the first event after start does. In the timer task, 
reset the counter only if it still holds the value that was checkpointed 
({{compareAndSet}}); otherwise it stays a little high, which only makes the 
next size checkpoint come earlier. A partition can get at most one more timer 
checkpoint per size checkpoint than before. Otherwise the size checkpoint, the 
timer task and the header {{CamelAzureEventHubsCheckpointUpdatedBy}} work as 
before. No option or default changes; the timer checkpoints at most once per 
window, as documented ("Works jointly with checkpointBatchSize"), so no upgrade 
guide entry.

camel-azure-eventhubs unit tests with the fix: 33 run, 0 failures. The 
integration tests (Azure) were not run.

How it was found: the backlog of an earlier review round (reading of 
{{processCommit}}); the user impact was then worked out from the code and the 
Event Hubs checkpoint semantics (a new owner of a partition starts at its 
checkpoint), and shown with the test.

Affected: main (cd2ce899764e; tested), camel-4.23.x and camel-4.22.x (the same 
per-partition code), camel-4.18.x ({{lastTask}} / {{lastScheduledTask}}, same 
shape) and camel-4.14.x ({{java.util.Timer}} task, same shape) - read, not run.

Duplicate check (2026-10-15): JIRA text "eventhubs checkpoint batch", 
"eventhubs checkpoint timeout", "checkpointBatchTimeout" (CAMEL-24198 
per-partition batching, CAMEL-24158 umbrella, CAMEL-17841 add batching: none 
about the cancelled task); GitHub pull requests "EventHubsConsumer checkpoint", 
"checkpointBatchTimeout" (#24903 = CAMEL-24198, #18957, #25247: other changes).

_Filed with Claude Code on behalf of allthingssecurity._




--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to