RESTEasy Reactive: Lock contention between callback processing and resume()
See original GitHub issueDescription
I was running some performance tests on Resteasy reactive and picked up some lock contention (about 11% of all contention during my load test) which I think may not be needed:
Its this code here on org.jboss.resteasy.reactive.common.core.AbstractResteasyReactiveContext:
synchronized void onComplete(Throwable throwable) {
if (completionCallbacks != null) {
for (CompletionCallback callback : completionCallbacks) {
callback.onComplete(throwable);
}
}
}
@Override
public synchronized void registerCompletionCallback(CompletionCallback callback) {
if (completionCallbacks == null) {
completionCallbacks = new ArrayList<>();
}
completionCallbacks.add(callback);
}
I am assuming the onComplete is contending with the resume() calls which also synchronize on the object.
Implementation ideas
In order to resolve this, and as a by-product avoid state issues of callbacks being added after they may have been processed, I suggest using an explicit lock and state flag as opposed to locking on (this):
private final Lock stateManagementLock = new ReentrantLock(); // Prevent race conditions on callbacks without needing to lock on (this)
private boolean completionCallbacksInvoked = false;
void onComplete(Throwable throwable) {
try {
stateManagementLock.lock();
if (completionCallbacks != null) {
for (CompletionCallback callback : completionCallbacks) {
callback.onComplete(throwable);
}
completionCallbacks = null;
}
completionCallbacksInvoked = true;
} finally {
stateManagementLock.unlock();
}
}
@Override
public void registerCompletionCallback(CompletionCallback callback) {
try {
stateManagementLock.lock();
if (completionCallbacksInvoked) {
throw new IllegalStateException("Completion callbacks cannot be registered after the context has been closed");
}
if (completionCallbacks == null) {
completionCallbacks = new ArrayList<>();
}
completionCallbacks.add(callback);
} finally {
stateManagementLock.unlock();
}
}
Issue Analytics
- State:
- Created 3 years ago
- Comments:20 (11 by maintainers)
Top Results From Across the Web
RESTEasy Reactive - To block or not to block - Quarkus
You have attempted to perform a blocking operation on a IO thread. This is not allowed, as blocking the IO thread will cause...
Read more >ResumeCallback (RESTEasy JAX-RS 3.0-beta-1 API)
A resume callback notification method that will be invoked in case the asynchronous response is being resumed by an error (e.g. in case...
Read more >Chapter 21. Remote API Red Hat JBoss BPM Suite 6.4
Red Hat JBoss BPM Suite provides various ways how to access the execution server in Business Central remotely including REST, JMS, SOAP, and...
Read more >chore(deps): update dependency io.quarkus:quarkus ... - GitLab
Unit as a return type; #23503 - Fix param converter processing in Resteasy Reactive ... Reactive: Lock contention between callback processing and resume()...
Read more >Kogito Documentation - KIE
Kogito is a cloud-native business automation technology for building cloud-ready business applications. The name Kogito derives from the ...
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Very reasonable. Cannot see why one would ever go from worker back to eventloop on purpose
On Fri, Mar 19, 2021 at 9:26 AM Georgios Andrianakis < @.***> wrote:
https://github.com/quarkusio/quarkus/pull/15882 should take care of it