shashank created CAMEL-25684:
--------------------------------

             Summary: camel-slack - the consumer skips the messages of a poll 
it did not route when the route is suspended during that poll
                 Key: CAMEL-25684
                 URL: https://issues.apache.org/jira/browse/CAMEL-25684
             Project: Camel
          Issue Type: Bug
          Components: camel-slack
            Reporter: shashank
            Assignee: shashank


{{SlackConsumer.createExchanges}} moves {{timestamp}} to the most recent 
message of the poll (lines 152 / 161 at main cd2ce899764e) before 
{{processBatch}} routes the messages. {{processBatch}} (172-192) stops when 
{{isBatchAllowed()}} is false, which {{ScheduledBatchPollingConsumer}} (104) 
returns when the route is being suspended ({{RouteController.suspendRoute}}, 
also from a route policy that suspends the route through the route controller 
such as {{DurationRoutePolicy}}, or {{CamelContext.suspend()}}, which resumes 
the same consumer): the message that is being routed completes and the rest of 
the batch is not routed. When the route is resumed the same consumer asks Slack 
for the messages after {{timestamp}} only, so the messages of that poll that 
were not routed are never routed. Nothing is logged. With the defaults the most 
recent message is routed first, so the older messages of the poll are lost: the 
rest of that poll, which since CAMEL-25523 can be several pages of 
{{maxResults}} (default 10) messages each.

This is the shape that CAMEL-25570 fixed in aws2-ddbstream. A consumer 
suspended directly ({{consumer.suspend()}}, as {{ScheduledRoutePolicy}} and the 
throttling route policies do) does not end the batch and is not affected; a 
route that is stopped and started (a new consumer) is not affected either.

h3. Reproduction

New {{SlackConsumerSuspendedBatchTest}} (4 tests): a real route against a small 
local HTTP server that answers {{conversations.history}} as Slack does 
(messages after {{oldest}}, most recent first). The processor of one message 
suspends the route from another thread and waits until the batch has ended; 
then the route is resumed; the fourth test suspends and resumes the 
{{CamelContext}}. On main all 4 fail: {{expected: <[m5, m4, m3, m2]> but was: 
<[m5, m4]>}}, in natural order {{expected: <[m2, m3, m4, m5]> but was: <[m2, 
m3]>}}, with a message posted while suspended {{expected: <[m5, m6, m4, m3, 
m2]> but was: <[m5, m6]>}}, and for the context suspend {{expected: <[m5, m4, 
m3, m2]> but was: <[m5, m4]>}}. The same tests with the pooled exchange 
factory, plus a check of its statistics (the exchanges of the messages that 
were not routed are given back once), fail on main as well.

h3. Proposed fix

* The messages that were not routed are kept and routed by the next poll, 
together with the messages posted in the meantime, in the order of the 
endpoint. The timestamp cannot simply stay before them as in the ddbstream fix: 
by default the most recent message is routed first, so the messages that were 
not routed are older than the ones that were, and a timestamp before them would 
route those again.
* As in the ddbstream fix, the exchanges of those messages are given back to 
the exchange factory, and {{processBatch}} returns the number of exchanges it 
routed (used for {{sendEmptyMessageWhenIdle}} and greedy polling) instead of 
the number it was given.
* The timestamp is now set in {{poll()}} instead of in {{createExchanges}} 
(same value).
* An upgrade guide entry (4.24). The kept messages are in memory only: a route 
that is stopped and started again does not route them (a new consumer).

camel-slack tests with the fix (built with the current core modules): 19 run, 0 
failures, 1 skipped (as on main).

How it was found: a TLA+ model of the poll (fetch, route one message at a time 
while the batch is allowed, end of the batch, suspend and resume as environment 
steps) violates "between two polls the consumer has not moved past a message it 
did not route" on main (5 states), holds with the change (newest-first and 
natural order); then the test.

Affected: main (cd2ce899764e; tested), camel-4.23.x, camel-4.22.x, 
camel-4.18.x, camel-4.14.x (the same {{createExchanges}} / {{processBatch}}; 
read, not run).

Duplicate check (2026-10-15): JIRA component camel-slack, text "slack consumer 
suspend" (CAMEL-25523, reading the following pages of the history, already 
fixed - a different cause of skipped messages); GitHub pull requests 
"SlackConsumer" (#27674 = CAMEL-25523, merged; nothing open).

_Filed with Claude Code on behalf of allthingssecurity._




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

Reply via email to