shashank created CAMEL-25523:
--------------------------------
Summary: camel-slack - the consumer skips messages when more than
maxResults messages are posted between two polls
Key: CAMEL-25523
URL: https://issues.apache.org/jira/browse/CAMEL-25523
Project: Camel
Issue Type: Bug
Components: camel-slack
Reporter: shashank
{{SlackConsumer.poll()}} (lines 75-94 at main a6979506bb1c) makes one
{{conversations.history}} request with {{oldest}} set to the timestamp of the
last consumed message and {{limit}} set to {{maxResults}} (default 10), routes
the messages of that response and sets the timestamp to the first of them
({{createExchanges}}, lines 96-123):
{code:java}
ConversationsHistoryResponse response =
slack.methods(token).conversationsHistory(req -> req
.channel(channelId)
.oldest(timestamp)
.limit(timestamp != null ?
Integer.parseInt(slackEndpoint.getMaxResults()) : 1));
...
Queue<Exchange> exchanges = createExchanges(response.getMessages());
{code}
Slack returns "the most recent messages in the time range first" and at most
{{limit}} of them; when there are more, {{has_more}} is true and
{{response_metadata.next_cursor}} points to the following, older, page. The
consumer ignores both. So when more than {{maxResults}} messages are posted to
the channel between two polls (default delay 10 seconds), it routes the
{{maxResults}} most recent ones, moves the timestamp past the others, and never
consumes them. Nothing is logged. With the docs example {{maxResults=1}}, any
two messages posted within one poll interval lose one of them. The docs say the
consumer "will consume only newer messages in the channel", i.e. all of them.
h3. Reproduction
New {{SlackConsumerHasMoreTest}}: a local HTTP server answers
{{conversations.list}} and {{conversations.history}} as Slack does ({{oldest}}
exclusive, most recent first, {{limit}} per page, {{has_more}} and
{{next_cursor}}), via the {{serverUrl}} option. The route uses
{{maxResults=2}}; after the first poll has routed the last message of the
history, five messages are posted at once. On main both tests (default order
and {{naturalOrder=true}}) fail twice:
{noformat}
mock://result Received message count. Expected: <5> but was: <2>
{noformat}
h3. Proposed fix
When a poll that follows the first one gets {{has_more}}, the consumer reads
the following pages with {{next_cursor}} (same {{limit}}) in the same poll and
routes all the messages, in the same order as before (most recent first, or
oldest first with {{naturalOrder}}); the timestamp is still the most recent
message. A poll with no more than {{maxResults}} new messages sends the same
single request as before, and the first poll (which reads the last message of
the history) is unchanged. A poll can now route more than {{maxResults}}
messages; the option description, the component docs (and the catalog copies)
say that {{maxResults}} is the number of messages per request, and the 4.23
upgrade guide has a note (raise {{maxResults}} for a busy channel to need fewer
requests). camel-slack tests with the fix: 8, 0 failures (1 skipped, needs a
Slack token).
Found with a Lean 4 model of the poll (a channel as a list of increasing
timestamps, the API as "after oldest, most recent first, limit per page"): "a
poll routes every message newer than the timestamp" fails for five new messages
and {{limit}} 2, and with {{limit}} 1 the second of two messages is never
routed by any later poll; main is proved to route at most {{limit}} messages
(so it misses some whenever more are new). The fix is proved to route exactly
the new messages for every channel, timestamp and {{maxResults}} >= 1, and to
send the same single request as main when no more than {{maxResults}} messages
are new. Confirmed with the real consumer.
Affected: main, camel-4.22.x, camel-4.18.x, camel-4.14.x (same code, GitHub
contents API).
Duplicate check (2026-10-10): JIRA text "slack" and "consumer" (17, none about
skipped messages; CAMEL-18187 is about pooled exchanges, CAMEL-12806 about an
empty list), "conversations.history" (none); GitHub pull requests
"SlackConsumer" (3, none related), "slack consumer" (none). No open pull
request changes {{SlackConsumer}}.
_Filed with Claude Code on behalf of allthingssecurity._
--
This message was sent by Atlassian Jira
(v8.20.10#820010)