[
https://issues.apache.org/jira/browse/CAMEL-25576?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Claus Ibsen updated CAMEL-25576:
--------------------------------
Fix Version/s: 4.24.0
> camel-box - event-logs/getEnterpriseEvents returns only the first chunk of
> the event log (at most 500 events); the events after it are dropped silently
> and cannot be requested
> -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
>
> Key: CAMEL-25576
> URL: https://issues.apache.org/jira/browse/CAMEL-25576
> Project: Camel
> Issue Type: Bug
> Components: camel-box
> Reporter: shashank
> Assignee: shashank
> Priority: Major
> Fix For: 4.24.0
>
>
> {{BoxEventLogsManager.getEnterpriseEvents}} (lines 68-96 at main
> c3829069cb72), the only method of the {{box:event-logs}} API:
> {code:java}
> EnterpriseEventsRequest request = new EnterpriseEventsRequest();
> request.position(position).after(after).before(before).types(types);
> EventLog eventLog = EventLog.getEnterpriseEvents(boxConnection, request);
> List<BoxEvent> results = new ArrayList<>();
> for (BoxEvent event : eventLog) {
> results.add(event);
> }
> return results;
> {code}
> An {{EventLog}} of box-java-sdk 4.16.4 is one response of the events
> endpoint: {{EnterpriseEventsRequest}} asks for {{limit = 500}} (the constant
> in its constructor), and the response has the events of that chunk and
> {{getNextStreamPosition()}} for the next one. The manager sends one request
> and returns the events of that response. It does not read the next stream
> position and does not return it either (the result is a plain
> {{List<BoxEvent>}}).
> So when more than 500 events lie between {{after}} and {{before}}, the caller
> gets the first 500 and has no means to ask for the rest: the {{position}}
> parameter needs a stream position, which only the dropped {{EventLog}} had.
> Nothing is logged. The javadoc of the method says "@return A list of all the
> events that met the given criteria", and for {{position}}: "May be null in
> which case all events within bounds returned".
> h3. Reproduction
> New {{BoxEventLogsManagerPagingTest}} (3 tests) in camel-box-component. A
> real {{BoxAPIConnection}} gets a {{RequestInterceptor}} that answers the
> events request from memory like the service: at most 500 events from the
> requested {{stream_position}}, and {{next_stream_position}} (the fake fails
> the test after 20 requests). So the SDK parses real responses. On main all 3
> fail:
> * {{returnsTheEventsOfEveryChunk}} (1200 events): {{all the events within
> bounds, not only the first chunk ==> expected: <1200> but was: <500>}}.
> * {{startsAtThePositionOfTheCallerAndReadsToTheEnd}} (position 100 of 1200):
> 1100 events expected, 500 returned.
> * {{stopsWhenTheServiceDoesNotMoveThePosition}}: {{expected: <2> but was:
> <1>}} (requests; it checks that the new loop ends when a response repeats the
> position it was asked for, and that events returned twice are kept once).
> h3. Proposed fix
> In {{BoxEventLogsManager.getEnterpriseEvents}}: read on from
> {{getNextStreamPosition()}} until a chunk is empty, which is the end of the
> events within bounds; also stop when the service returns no next position or
> the position it was asked for. The events are collected in a
> {{LinkedHashSet}} ({{BoxResource.equals}} compares the id), so an event that
> the service returns in two chunks is kept once and the order of the service
> is kept. The signature is unchanged; the javadoc of the return value now says
> that the log is read chunk by chunk and kept in memory.
> Behaviour change, with a 4.24 upgrade-guide entry: the operation returns all
> the events between {{after}} and {{before}}. Cost: one request per chunk of
> 500 events and one more that finds the end (two requests where main sent one,
> when everything fits in one chunk). A wide {{after}} / {{before}} window now
> returns every event in one list, with that many requests and more memory; the
> upgrade note and the javadoc say to narrow the window for a large event log.
> The loop has no limit of its own on the number of chunks: it ends on an empty
> chunk, on a missing next position or on a position that did not move. I end
> the loop on an empty chunk and not on a chunk shorter than the limit because
> I could not confirm from the SDK that a short chunk always means the end.
> camel-box-api and camel-box-component unit tests with the fix: 6, 0 failures
> (the integration tests need a Box account and were not run; nothing was run
> against Box).
> Found with a Lean 4 model of a position-paged service: the event log is a
> list, a response is a {{take}} / {{drop}} slice of it and the position after
> it. Property: the result is the log from the position of the caller to its
> end, every event once and in order. Counterexample for main: with chunks of
> two, {{[1, 2, 3]}} gives {{[1, 2]}} ({{cex_third_event_dropped}}); with a
> chunk of 500, 501 events give 500 ({{cex_501_events}}). In the model, reading
> chunk after chunk returns the list from the start position to its end
> ({{fix_meets_spec}}), and the same as main when the events fit in one chunk
> ({{fix_eq_main_one_chunk}}). The model says nothing about the real service.
> Then confirmed with the real class as described.
> Affected: main (4.23.0-SNAPSHOT at c3829069cb72), and the release branches
> camel-4.18.x (c3fd5317a5a0), camel-4.22.x (2821f284056c) and camel-4.23.x
> (197e70656a41): lines 66-95 of {{BoxEventLogsManager}} (the javadoc of the
> return value and the whole method body) are identical to main on all three.
> Read, not run.
> Duplicate check (2026-10-12): JIRA text "box getEnterpriseEvents" (none),
> "box enterprise events position" (2, unrelated: CAMEL-12998, CAMEL-12297);
> GitHub pull requests "box enterprise events": none; no open pull request
> touches camel-box.
> _Filed with Claude Code on behalf of allthingssecurity._
--
This message was sent by Atlassian Jira
(v8.20.10#820010)