Skip to content

Commit c0c0827

Browse files
authored
Add ActionListener.releaseBefore (#123591)
This commit introduces a new helper function, ActionListener.releaseBefore, which ensures that a resource is released before the listener is notified.
1 parent 6b27e42 commit c0c0827

File tree

3 files changed

+41
-5
lines changed

3 files changed

+41
-5
lines changed

server/src/main/java/org/elasticsearch/action/ActionListener.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import java.util.function.Consumer;
2929
import java.util.function.Function;
3030

31+
import static org.elasticsearch.action.ActionListenerImplementations.checkedRunnableFromReleasable;
3132
import static org.elasticsearch.action.ActionListenerImplementations.runnableFromReleasable;
3233
import static org.elasticsearch.action.ActionListenerImplementations.safeAcceptException;
3334
import static org.elasticsearch.action.ActionListenerImplementations.safeOnFailure;
@@ -335,6 +336,16 @@ static <Response> ActionListener<Response> runBefore(ActionListener<Response> de
335336
return assertOnce(new ActionListenerImplementations.RunBeforeActionListener<>(delegate, runBefore));
336337
}
337338

339+
/**
340+
* Wraps a given listener and returns a new listener which releases the provided {@code releaseBefore}
341+
* resource before the listener is notified via either {@code #onResponse} or {@code #onFailure}.
342+
*/
343+
static <Response> ActionListener<Response> releaseBefore(Releasable releaseBefore, ActionListener<Response> delegate) {
344+
return assertOnce(
345+
new ActionListenerImplementations.RunBeforeActionListener<>(delegate, checkedRunnableFromReleasable(releaseBefore))
346+
);
347+
}
348+
338349
/**
339350
* Wraps a given listener and returns a new listener which makes sure {@link #onResponse(Object)}
340351
* and {@link #onFailure(Exception)} of the provided listener will be called at most once.

server/src/main/java/org/elasticsearch/action/ActionListenerImplementations.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,20 @@ public String toString() {
5858
};
5959
}
6060

61+
static CheckedRunnable<Exception> checkedRunnableFromReleasable(Releasable releasable) {
62+
return new CheckedRunnable<>() {
63+
@Override
64+
public void run() {
65+
Releasables.closeExpectNoException(releasable);
66+
}
67+
68+
@Override
69+
public String toString() {
70+
return "release[" + releasable + "]";
71+
}
72+
};
73+
}
74+
6175
static void safeAcceptException(Consumer<Exception> consumer, Exception e) {
6276
assert e != null;
6377
try {

server/src/test/java/org/elasticsearch/action/ActionListenerTests.java

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import java.util.concurrent.atomic.AtomicBoolean;
2929
import java.util.concurrent.atomic.AtomicInteger;
3030
import java.util.concurrent.atomic.AtomicReference;
31+
import java.util.function.BiFunction;
3132
import java.util.function.Consumer;
3233

3334
import static org.hamcrest.Matchers.containsString;
@@ -610,16 +611,26 @@ public String toString() {
610611
);
611612
}
612613

614+
public void testReleaseBefore() {
615+
runReleaseListenerTest(true, false, (delegate, releasable) -> ActionListener.releaseBefore(releasable, delegate));
616+
runReleaseListenerTest(true, true, (delegate, releasable) -> ActionListener.releaseBefore(releasable, delegate));
617+
runReleaseListenerTest(false, false, (delegate, releasable) -> ActionListener.releaseBefore(releasable, delegate));
618+
}
619+
613620
public void testReleaseAfter() {
614-
runReleaseAfterTest(true, false);
615-
runReleaseAfterTest(true, true);
616-
runReleaseAfterTest(false, false);
621+
runReleaseListenerTest(true, false, ActionListener::releaseAfter);
622+
runReleaseListenerTest(true, true, ActionListener::releaseAfter);
623+
runReleaseListenerTest(false, false, ActionListener::releaseAfter);
617624
}
618625

619-
private static void runReleaseAfterTest(boolean successResponse, final boolean throwFromOnResponse) {
626+
private static void runReleaseListenerTest(
627+
boolean successResponse,
628+
final boolean throwFromOnResponse,
629+
BiFunction<ActionListener<Void>, Releasable, ActionListener<Void>> releaseListenerProvider
630+
) {
620631
final AtomicBoolean released = new AtomicBoolean();
621632
final String description = randomAlphaOfLength(10);
622-
final ActionListener<Void> l = ActionListener.releaseAfter(new ActionListener<>() {
633+
final ActionListener<Void> l = releaseListenerProvider.apply(new ActionListener<>() {
623634
@Override
624635
public void onResponse(Void unused) {
625636
if (throwFromOnResponse) {

0 commit comments

Comments
 (0)