allthingssecurity opened a new pull request, #29787: URL: https://github.com/apache/camel/pull/29787
# Description [CAMEL-26883](https://issues.apache.org/jira/browse/CAMEL-26883) `DefaultBacklogDebugger.NodeBreakpoint.matchProcess` registers the `SuspendedExchange` of an exchange at a node with `suspendedBreakpoints.putIfAbsent(nodeId, se)`, but `beforeProcess` then works by key only: it puts the message of its exchange with `suspendedBreakpointMessages.put(nodeId, msg)`, waits on `suspendedBreakpoints.get(nodeId)` (not on the `SuspendedExchange` its own `matchProcess` registered), and on a timeout removes both entries by key. Found with a TLA+ model of this protocol (two exchanges at one breakpoint node and the debugger client), then reproduced with the real classes. It needs concurrent consumers and a resume (or a step, a skip over, a removal or a disable of the breakpoint) at the moment an exchange has just matched a breakpoint and still dumps its message; `resumeAll` from `camel debug` resumes such an exchange, which the user has not seen yet: - Exchange E1 matches the breakpoint at node N; the user resumes N before E1 reached its wait (E1 first dumps its message, which takes a while for a large body); exchange E2 then suspends at N. E1 finds E2's `SuspendedExchange` and waits on it, until E2 is resumed or the fallback timeout (300 seconds by default), although E1 was resumed; and E1's message replaces E2's, so the debugger shows E1's message for the exchange that is suspended (E2), and the body and header setters of the debugger act on E2. - E1 times out at N while the user resumes N and E2 suspends at N: E1's timeout removes E2's `SuspendedExchange` and message, so E2 waits invisible (`getSuspendedBreakpointNodeIds` is empty, `resumeBreakpoint(N)` does nothing) until its own timeout. Change, in `DefaultBacklogDebugger`: - `NodeBreakpoint.beforeProcess` suspends only on the `SuspendedExchange` of its own exchange: when it is gone (resumed meanwhile) or belongs to another exchange, the exchange continues. Its message is published only while its `SuspendedExchange` is the one at the node, in one `compute` with that check (a resume and another exchange can come in between). After the wait it removes its message by exchange id (the debugger replaces the message object when the body or a header is changed at the breakpoint), and on a timeout its `SuspendedExchange` by value; - the single-step breakpoints remove their entries the same way on a timeout; - `singleStepExchangeId`, changed by the threads of the debugger client and of the exchanges, is a `ConcurrentLinkedDeque` (was an `ArrayDeque`; by reading, not covered by a test). It is still one suspended exchange per node (`putIfAbsent` in `matchProcess`), and a timeout still removes the entries of its own exchange, as CAMEL-21747 added. A statement-level model of the committed code holds for two exchanges, the resume and the timeout (it does not cover the step breakpoints or the message refresh; the second test covers the refresh). With one exchange at a node at a time, the only difference: when the breakpoint is resumed (or the debugger disabled) while the exchange still dumps its message, the exchange no longer leaves its message behind at the node. Tests, new `BacklogDebuggerResumedBeforeSuspendTest` (camel-management, next to `BacklogDebuggerEdgeCasesTest`): - `testResumedBeforeTheExchangeSuspended`: E1 matches the breakpoint and is held while the debugger dumps its message (a body whose conversion to text waits on a latch, only at the breakpoint); the test resumes the breakpoint, sends E2, which suspends there, then releases E1. E1 must reach the end of the route without another resume, and the debugger must still show E2 (its exchange id and body) as the suspended exchange; then E2 is resumed. Without the change E1 waits on E2's latch (the mock times out); - `testTimeoutAfterTheBodyWasChangedLeavesNoMessage`: the body is changed at the breakpoint, the breakpoint times out (fallback timeout 2 seconds), and no message or suspended exchange is left at the node. It passes on main too; it is the only test of the changed timeout path, and it guards the removal by exchange id (a removal by message object would leave the replaced message behind). The timeout scenario with two exchanges is covered by the model, not by a test. With it the camel-core tests (9181 run, 0 failures, 45 skipped) and the camel-management tests (603 run, 0 failures, 1 skipped) pass, and the debugger tests again on the final commit (`BacklogDebugger*Test` and `*Debugger*Test`, 24 run, 0 failures). No documentation or upgrade guide change. # Target - [x] I checked that the commit is targeting the correct branch (Camel 4 uses the `main` branch) # Tracking - [x] If this is a large change, bug fix, or code improvement, I checked there is a [JIRA issue](https://issues.apache.org/jira/browse/CAMEL) filed for the change (usually before you start working on it): [CAMEL-26883](https://issues.apache.org/jira/browse/CAMEL-26883). # Apache Camel coding standards and style - [x] I checked that each commit in the pull request has a meaningful subject line and body. - [ ] I have run `mvn clean install -DskipTests` locally from root folder and I have committed all auto-generated changes. (I built the core modules and camel-management with the formatter and import-sort plugins and ran the tests named above. I did not run the full root build.) # AI-assisted contributions - [x] If this PR includes AI-generated code, commits have proper co-authorship attribution (e.g., `Co-authored-by` trailers) and the PR description identifies the AI tool used. This PR was prepared with Claude Code (Claude Opus 5.5). The commit carries a `Co-Authored-By` trailer. _Claude Code on behalf of allthingssecurity_ 🤖 Generated with [Claude Code](https://claude.com/claude-code) -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
