eclipse-ee4j / eclipse-ee4j/jersey
Jersey async client race between future and callback
- Dominant language
- Java
- Stars
- 730
- Forks
- 382
- PR merge metrics
- No merged PRs in 30d
Description
Hi,
testing async code, I encountered a race condition I believe between callbacks and futures.
My scenario: I need to get 400 Post requests out as quickly as possible. I decided to go with async requests and let jersey handle everything else. My code looks slightly like that:
// create lists of messages to get out
// submit 10 messages to one worker thread
// worker thread submits async call with callback to jersey:
Future post = request.async().post(Entity.entity(postBody, MediaType.APPLICATION_JSON_TYPE), callback);
// callback reacts to failures and success by tracking the key to the status
After this, i need to release all messages, so I wait for jersey to finish processing like this:
for(Future f : collectedFutures)
{ f.get(3000, TimeUnit.Milliseconds); }
This code works fine, no timeout/interrupts or anything similar thrown.
However, when releasing all messages, I take the callback (which tracked all statuses) and release the messages based on their status. (success,retry etc).
Turns out, at that point, even though the get() has returned, the callback has not yet been invoked. In my logs I can see that the callback is invoked around 50-100ms later, so I believe this is a race between jersey marking the Future as done, and notifying the callback with the result, and the get() method returning when finished.
I believe the future should ONLY return the get() call if the callback has been invoked (if there is a callback).
My current workaround is to process the futures in addition to the callback. So that if the callback is not on time, the future can process the status separately. This sort of duplicates code, but I couldn't find a different workaround.
I believe the issue here is in JerseyInvocation#933 and friends. The callback function is not overwritable, and it clearly sets the future to be complete before invoking the callback.
Please let me know if you have any questions
#### Environment
Mac OS 10.10.5,
Jersey-client 2.22.1
Eclipse 4.5.0
#### Affected Versions
[2.22.1]
Contributor guide
Research direction
Start by reading JerseyInvocation#933 and the surrounding async Future and callback handling. Reproduce the Jersey-client 2.22.1 scenario with an asynchronous POST, then verify that Future.get() and callback invocation occur in the intended order. Done means the race is resolved and coverage confirms the callback has run when get() returns.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java
- Domain
- api
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 42/100