allthingssecurity opened a new pull request, #27692:
URL: https://github.com/apache/camel/pull/27692

   # Description
   
   [CAMEL-25544](https://issues.apache.org/jira/browse/CAMEL-25544)
   
   The Jira REST client is asynchronous: the methods of `IssueRestClient` 
return a `Promise`, and `claim()` waits for the answer and throws 
`RestClientException` when Jira rejected the request. `AddIssueProducer` and 
`UpdateIssueProducer` claim the promise, but the other producers that change an 
issue dropped it: `addComment`, `addIssueLink`, `addWorkLog`, `attach`, 
`deleteIssue`, `transitionIssue` (the transition and its comment), `watchers`, 
and `addIssue` for its watchers.
   
   So `process()` returned at once. A request that Jira rejected (no 
permission, a transition the workflow does not allow, a missing field, HTTP 
401/403/5xx, a network error) was not noticed: the exchange completed 
successfully, nothing was logged, and the change was missing in Jira. The route 
also continued before Jira had done the work; for `attach`, the route continued 
before the upload finished.
   
   Now these producers claim the promise of each request. A rejected request 
fails the exchange with the `RestClientException` of the client, and the route 
continues when Jira has answered. The 4.23 upgrade guide has a note (routes 
that relied on such failures being ignored must handle the exception).
   
   Partial failure: a producer that sends several requests can now fail after 
some of them were done. `transitionIssue` can fail on its comment after the 
transition was made, and `watchers` and `addIssue` can fail after some of the 
watchers were changed; a retry or redelivery repeats the earlier requests. For 
`addIssue` a redelivery would create a second issue, so it now sets the created 
issue as the message body before it adds the watchers (it did that after them): 
when adding a watcher fails, the created issue is on the exchange for the error 
handling of the route. The upgrade guide note says this too.
   
   Timeout: `claim()` waits without a timeout on the Camel side. How long a 
producer can block is bounded only by the timeouts of the Jira client's HTTP 
client, which camel-jira does not set or expose. This is the same for 
`addIssue`, `updateIssue` and the fetch producers today.
   
   Tests:
   - New `DeleteIssueProducerFailureTest` uses the real Jira client against a 
local HTTP server: a `DELETE` answered with 403 fails the exchange with a 
`RestClientException` (status 403), and one answered with 204 completes it. 
Without the change the 403 test fails in any case (the exchange has no 
exception). The 204 test, `completesTheExchangeWhenJiraDeletedTheIssue`, fails 
on main only through timing: its assertion on the received requests runs before 
the request has reached the server (`expected: <[DELETE 
/rest/api/latest/issue/TST-1]> but was: <[]>`), which was the case in both runs 
on main but is not guaranteed. It is not a deterministic reproducer; it is 
there to cover the successful path with the real client.
   - New `JiraProducerRejectedRequestTest` (mocked `IssueRestClient`, as the 
other producer tests; every changing request returns a rejected promise): one 
test per producer, 9 in total. Without the change all fail with `expected: 
<RestClientException...> but was: <null>`. A 10th test, 
`addIssueKeepsTheCreatedIssueWhenAWatcherFails`, checks that the created issue 
is the message body when adding a watcher is rejected; with the old order it 
fails (the body is still the description).
   - The mocks of nine existing producer tests returned `null` for these calls 
and now return a completed promise.
   - With the change: camel-jira 58 tests, 0 failures.
   
   The cost is that these producers now block the calling thread until Jira 
answers, like `addIssue`, `updateIssue` and the fetch producers already do.
   
   Found by comparing the producers and with a small TLA+ model of one exchange 
(send, answer, return of `process()`, close of the body): on main "a successful 
exchange did not have its request rejected" and "the route continues only when 
Jira has answered" are violated in 3 to 4 steps; with the fix they hold. I then 
reproduced it with the real client. (The model also has a property about an 
attachment being read after the exchange released it; no test shows that with 
the real client, so I do not claim it here.)
   
   # 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).
   
   # 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 and tested camel-jira, including the formatter and import-sort 
plugins. 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]

Reply via email to