Comments (3)
Just for a quick illustration of the problem: Basically this is what happens:
public class CompletableFutureTest {
public static void main(String[] args) throws InterruptedException {
Executor executor = Executors.newSingleThreadScheduledExecutor();
System.out.println(Thread.currentThread().getId() + ": Main thread");
CompletableFuture<Void> f = new CompletableFuture<>();
executor.execute(() -> {
try {
f.whenComplete((r, e) -> {
System.out.println(Thread.currentThread().getId() + ": Complete!");
});
Thread.sleep(1000);
f.complete(null);
} catch (Exception e) {
e.printStackTrace();
}
});
Thread.sleep(3000);
f.thenCompose(v -> {
System.out.println(Thread.currentThread().getId() + ": thenCompose!");
return new CompletableFuture<>();
});
}
}
Output is:
1: Main thread
10: Complete!
1: thenCompose!
That means that the Function we pass in "thenCompose" is executed on the main thread, but copycat expects it to be executed on the same thread as the one writing "10: Complete!".
from copycat.
The Copycat client internals have been completely rewritten, but I think we still do need to do some review of that code before a full release to make sure this issue is not present. I've seen some non-intuitive behavior in CompletableFuture
, particularly with thenCompose
.
@bgloeckle correct me if I'm wrong, but essentially what you're seeing is if the main thread gets to the thenCompose
call after the future being composed is completed, CompletableFuture
will run the composed callback on the main thread rather than the thread that completed it?
A while back, we actually had similar issues with thenComposeAsync
causing deadlocks in the server. I found an obscure reference to an issue in the CompletableFuture
implementation that was fixed in some later Java releases, and I removed all use of thenComposeAsync
.
I think I may just want to do the same thing and replace thenCompose
calls with a helper for internal use that ensures composed callbacks are executed on the proper thread (the thread that completed the future). Its use only seems to be safe inside the Copycat server where futures are created and completed on the same thread. Most of the other code that completes futures on a thread other than the one on which it was created already account for this issue by explicitly complete
ing futures in a specific thread.
I will go through and check all the uses of this method. If this pattern isn't being used in the new client I'll close this.
from copycat.
@bgloeckle correct me if I'm wrong, but essentially what you're seeing is if the main thread gets to the thenCompose call after the future being composed is completed, CompletableFuture will run the composed callback on the main thread rather than the thread that completed it?
Yes, that's what I was seeing (I think that was on the "beta5" release). I did not yet check all the code again for the newer releases (I'm just in the process of switching diqube to copycat rc2), but essentially all the methods that create the "pipeline" that will be executed as soon as a CompletableFuture is completed should themselves take care of being executed on the correct thread. I think it's a good idea to have a single utility class for that in copycat.
from copycat.
Related Issues (20)
- Support concurrent access of logs
- Remove indexing in logs
- Relax threading model in transports
- Remove serialization
- Create state machine test framework
- Support relaxed client consistency models
- Use unique node identifiers HOT 2
- Catch up joining nodes in the PASSIVE state before promotion to ACTIVE HOT 1
- question for performance HOT 4
- Join request from leader is proxied back to itself
- Leader election sends LEADER state change event twice
- New leader triggers onLeave event
- Use trace log level for requests/responses
- Don't submit unnecessary keep-alives
- Nodes can't communicate over the internet HOT 1
- copycat 1.2.4 server fails build test HOT 2
- question about pessimistic case HOT 1
- Allow KeepAliveRequest to manage multiple sessions HOT 2
- Under certain disconnection circumstances, the copycat-client-io thread takes 100% CPU HOT 3
- ServerCommit GC Warning
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from copycat.