-
Notifications
You must be signed in to change notification settings - Fork 24.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Assert not same executor when completing future #108934
Changes from all commits
4f1a539
d84d275
39450b7
ef2a6a4
a7b6a85
41c54e1
7722a9e
1508a6f
43a477b
4cc0c59
7896110
199676e
2e031fb
8de5f11
6554796
356a846
a6466a2
aec8017
c6f9c32
ce01fd9
7205c23
ac36c97
1edb078
1c1d48a
bedbda8
0992112
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License | ||
* 2.0 and the Server Side Public License, v 1; you may not use this file except | ||
* in compliance with, at your election, the Elastic License 2.0 or the Server | ||
* Side Public License, v 1. | ||
*/ | ||
|
||
package org.elasticsearch.action.support; | ||
|
||
import org.elasticsearch.common.util.concurrent.EsExecutors; | ||
import org.elasticsearch.core.CheckedConsumer; | ||
|
||
import java.util.Objects; | ||
|
||
/** | ||
* An unsafe future. You should not need to use this for new code, rather you should be able to convert that code to be async | ||
* or use a clear hierarchy of thread pool executors around the future. | ||
* | ||
* This future is unsafe, since it allows notifying the future on the same thread pool executor that it is being waited on. This | ||
* is a common deadlock scenario, since all threads may be waiting and thus no thread may be able to complete the future. | ||
*/ | ||
@Deprecated(forRemoval = true) | ||
public class UnsafePlainActionFuture<T> extends PlainActionFuture<T> { | ||
|
||
private final String unsafeExecutor; | ||
private final String unsafeExecutor2; | ||
|
||
public UnsafePlainActionFuture(String unsafeExecutor) { | ||
this(unsafeExecutor, null); | ||
} | ||
|
||
public UnsafePlainActionFuture(String unsafeExecutor, String unsafeExecutor2) { | ||
Objects.requireNonNull(unsafeExecutor); | ||
this.unsafeExecutor = unsafeExecutor; | ||
this.unsafeExecutor2 = unsafeExecutor2; | ||
} | ||
|
||
@Override | ||
boolean allowedExecutors(Thread thread1, Thread thread2) { | ||
return super.allowedExecutors(thread1, thread2) | ||
|| unsafeExecutor.equals(EsExecutors.executorName(thread1)) | ||
|| unsafeExecutor2 == null | ||
|| unsafeExecutor2.equals(EsExecutors.executorName(thread1)); | ||
} | ||
|
||
public static <T, E extends Exception> T get(CheckedConsumer<PlainActionFuture<T>, E> e, String allowedExecutor) throws E { | ||
PlainActionFuture<T> fut = new UnsafePlainActionFuture<>(allowedExecutor); | ||
e.accept(fut); | ||
return fut.actionGet(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -59,6 +59,7 @@ | |
import org.elasticsearch.action.search.TransportSearchAction; | ||
import org.elasticsearch.action.search.TransportSearchScrollAction; | ||
import org.elasticsearch.action.support.PlainActionFuture; | ||
import org.elasticsearch.action.support.UnsafePlainActionFuture; | ||
import org.elasticsearch.action.termvectors.MultiTermVectorsAction; | ||
import org.elasticsearch.action.termvectors.MultiTermVectorsRequest; | ||
import org.elasticsearch.action.termvectors.MultiTermVectorsRequestBuilder; | ||
|
@@ -410,7 +411,13 @@ protected <Request extends ActionRequest, Response extends ActionResponse> void | |
* on the result before it goes out of scope. | ||
* @param <R> reference counted result type | ||
*/ | ||
private static class RefCountedFuture<R extends RefCounted> extends PlainActionFuture<R> { | ||
// todo: the use of UnsafePlainActionFuture here is quite broad, we should find a better way to be more specific | ||
// (unless making all usages safe is easy). | ||
private static class RefCountedFuture<R extends RefCounted> extends UnsafePlainActionFuture<R> { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yikes. I suspect we can/should move all usages of this into tests, and do the ref-counting (and asyncification) properly in prod code. But I see that's not a small change. Ok for now... There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, I also pondered on this for a short while, but decided to defer this issue for now. I think I agree to move to all prod client interactions being async now. If it is too big we would need to stop notifying on generic thread pool (one more pool maybe, hopefully as an interim step). We can discuss more when we tackle it. |
||
|
||
private RefCountedFuture() { | ||
super(ThreadPool.Names.GENERIC); | ||
} | ||
|
||
@Override | ||
public final void onResponse(R result) { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I opted to add this unsafe variant that is then used in all places where I found conflicts, since fixing them all would make this PR size unmanageable. Using this we can now fix them one by one, spreading out the load too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 can we mark this as
@Deprecated(forRemoval = true)
so that IDEs highlight its usages?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need a task/issue/ticket on fixing them one-by-one?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think one by one is too granular. I'll probably create area level ones (perhaps a bit more granular, for instance the one in
AbstractClient
needs a separate one).