shashank created CAMEL-25727:
--------------------------------
Summary: camel-aws-cloudtrail - the consumer never routes an event
that CloudTrail makes visible after a newer one, because each lookup starts at
the newest event time already seen
Key: CAMEL-25727
URL: https://issues.apache.org/jira/browse/CAMEL-25727
Project: Camel
Issue Type: Bug
Components: camel-aws
Reporter: shashank
Assignee: shashank
Since CAMEL-24082 the {{aws-cloudtrail}} consumer keeps a per-consumer cursor:
each poll calls {{LookupEvents}} with {{startTime}} = the newest event time it
has seen, reads every page, and skips the events seen at exactly that instant
by event id ({{CloudtrailConsumer.poll}}, main 55ed20f14e90, lines 77-79 and
94-119).
AWS does not document that {{LookupEvents}} sees events in the order of their
event time, and it documents a delivery delay. The AWS CloudTrail FAQ
(https://aws.amazon.com/cloudtrail/faqs/, "How long does it take CloudTrail to
deliver an event for an API call?") says: "Typically, CloudTrail delivers an
event within 5 minutes of the API call." For trails, the user guide
(https://docs.aws.amazon.com/awscloudtrail/latest/userguide/how-cloudtrail-works.html)
says "CloudTrail typically delivers logs within an average of about 5 minutes
of an API call. This time is not guaranteed." The {{eventTime}} of an event is
the time of the API call. With a delay that varies per event, two API calls A
(12:00:00) and B (12:00:30) can become visible in the order B, A: B can be
visible to {{LookupEvents}} before A. A poll in between routes B and moves the
cursor to 12:00:30; when A becomes visible its event time is before every later
{{startTime}}, and it is never routed. Nothing is logged.
Trigger: default options (the consumer polls every 500 ms), any account where
API calls of different services are delivered with different delays. The loss
is silent and permanent for that event.
h3. Reproduction
New test
{{CloudtrailConsumerLateEventTest.lateEventWithEarlierEventTimeIsRoutedOnceByTheLookBack}}
with a mocked {{CloudTrailClient}} that answers like the service (only events
in [{{startTime}}, {{endTime}}], newest first) and a test clock: poll 1 sees
event "newer" (T+20 s); then event "late" (T+10 s) becomes visible; at T+60 s a
poll must route it. On main that poll routes nothing ({{expected: <1> but was:
<0>}}, 3 of 3 runs). The test needs the consumer's new clock hook {{now()}}
(and the other new tests the new options), so it does not compile against main
as committed; it was run against main's consumer with the {{@Override}} of
{{now()}} removed (main then ignores the test clock, which does not change this
sequence) and the four tests of the new options left out. With the fix,
removing only the call of the late-event lookup makes it fail the same way, and
{{lookBackWindowZeroBehavesAsBefore}} pins main's behaviour: the late event is
not routed.
h3. Proposed fix
The normal polls stay as they are: same {{LookupEvents}} requests, from the
newest event time seen. A separate late-event lookup runs every
{{lookBackInterval}} (new option, default 1 minute): it looks up the events
from {{lookBackWindow}} (new option, default 10 minutes) before now up to the
newest event time seen, never before the consumer start, and routes those it
has not routed yet (by event id). It sends one page per poll, so it adds at
most one request to a poll. If that request fails, the failure is logged (WARN,
the stack trace only at DEBUG), the events of the normal lookup are still
routed and the lookup starts again at the next interval. The ids of the routed
events are kept with their event time and dropped once that time is before
every later lookup, so the set only holds the events of the window.
{{lookBackWindow=0}} disables the lookup and gives exactly the previous
behaviour.
Defaults: 10 minutes is twice the "typically within 5 minutes" of the FAQ; 1
minute bounds the delay of a late event to about a minute after it becomes
visible, for one extra request per minute on a quiet account.
Cost: the late-event lookup sends ceil(N / maxResults) requests per
{{lookBackInterval}}, at most one per poll, where N is the number of events (of
the {{eventSource}}, if set) between {{lookBackWindow}} before now and the
newest event time seen; none when that event time is older than the window.
With the defaults: one request per minute up to 50 events in 10 minutes, 20 per
minute with 1000 events in 10 minutes. AWS allows two {{LookupEvents}} requests
per second per account and Region (120 per minute); the polls themselves send
at least one request every {{delay}} (500 ms by default, so up to about two per
second, as on main), and one more per further page of new events, as before. So
with the default {{delay}} the polls alone can already use most of that limit;
the late-event lookup adds one request per minute to it on a quiet account. The
option description, the component page and the upgrade note state this.
With the fix the camel-aws-cloudtrail tests pass: 7 run, 0 failures, 0 errors,
0 skipped (5 new). New tests (mocked client, test clock, no sleeps): the late
event is routed exactly once; between two late-event lookups each poll sends
the same requests as before (counted, no {{endTime}}); the lookup sends one
page per poll, starts at the consumer start and does not route events again,
and the id set empties once the window has passed; a failed late-event lookup
is logged and does not lose the events of the normal lookup of that poll;
{{lookBackWindow=0}} sends only the normal requests and does not route the late
event, as before.
Not covered: an event whose event time is before the consumer start (as
before), and an event that becomes visible more than {{lookBackWindow}} after
its event time. The CloudTrail refresh task of camel-aws-secrets-manager
({{CloudTrailReloadTriggerTask}}) moves its position in a similar way; not
changed here. Not run against AWS.
Affected: main (tested); camel-4.23.x, camel-4.22.x and camel-4.18.x have the
same cursor code (read, not run).
Duplicate check (2026-10-17): JIRA text "cloudtrail" (all issues; CAMEL-24082
fixed the static cursor, the paging and the +1 s skip, not late delivery);
GitHub pull requests "cloudtrail": only dependency bumps and CAMEL-24082.
_Filed with Claude Code on behalf of allthingssecurity._
--
This message was sent by Atlassian Jira
(v8.20.10#820010)