Skip to content

Commit e8b7027

Browse files
authored
Remove Throwable usage from transport modules (#30845)
Currently nio and netty modules use the CompletableFuture class for managing listeners. This is unfortunate as that class accepts Throwable. This commit adds a class CompletableContext that wraps the CompletableFuture but does not accept Throwable. This allows the modification of netty and nio logic to no longer handle Throwable.
1 parent 5a97423 commit e8b7027

File tree

26 files changed

+127
-67
lines changed

26 files changed

+127
-67
lines changed
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/*
2+
* Licensed to Elasticsearch under one or more contributor
3+
* license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright
5+
* ownership. Elasticsearch licenses this file to you under
6+
* the Apache License, Version 2.0 (the "License"); you may
7+
* not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
package org.elasticsearch.common.concurrent;
21+
22+
import java.util.concurrent.CompletableFuture;
23+
import java.util.function.BiConsumer;
24+
25+
/**
26+
* A thread-safe completable context that allows listeners to be attached. This class relies on the
27+
* {@link CompletableFuture} for the concurrency logic. However, it does not accept {@link Throwable} as
28+
* an exceptional result. This allows attaching listeners that only handle {@link Exception}.
29+
*
30+
* @param <T> the result type
31+
*/
32+
public class CompletableContext<T> {
33+
34+
private final CompletableFuture<T> completableFuture = new CompletableFuture<>();
35+
36+
public void addListener(BiConsumer<T, ? super Exception> listener) {
37+
BiConsumer<T, Throwable> castThrowable = (v, t) -> {
38+
if (t == null) {
39+
listener.accept(v, null);
40+
} else {
41+
assert !(t instanceof Error) : "Cannot be error";
42+
listener.accept(v, (Exception) t);
43+
}
44+
};
45+
completableFuture.whenComplete(castThrowable);
46+
}
47+
48+
public boolean isDone() {
49+
return completableFuture.isDone();
50+
}
51+
52+
public boolean isCompletedExceptionally() {
53+
return completableFuture.isCompletedExceptionally();
54+
}
55+
56+
public boolean completeExceptionally(Exception ex) {
57+
return completableFuture.completeExceptionally(ex);
58+
}
59+
60+
public boolean complete(T value) {
61+
return completableFuture.complete(value);
62+
}
63+
}

libs/elasticsearch-nio/build.gradle

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ publishing {
3333
}
3434

3535
dependencies {
36+
compile "org.elasticsearch:elasticsearch-core:${version}"
37+
3638
testCompile "com.carrotsearch.randomizedtesting:randomizedtesting-runner:${versions.randomizedrunner}"
3739
testCompile "junit:junit:${versions.junit}"
3840
testCompile "org.hamcrest:hamcrest-all:${versions.hamcrest}"

libs/elasticsearch-nio/src/main/java/org/elasticsearch/nio/BytesWriteHandler.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ public abstract class BytesWriteHandler implements ReadWriteHandler {
2828

2929
private static final List<FlushOperation> EMPTY_LIST = Collections.emptyList();
3030

31-
public WriteOperation createWriteOperation(SocketChannelContext context, Object message, BiConsumer<Void, Throwable> listener) {
31+
public WriteOperation createWriteOperation(SocketChannelContext context, Object message, BiConsumer<Void, Exception> listener) {
3232
assert message instanceof ByteBuffer[] : "This channel only supports messages that are of type: " + ByteBuffer[].class
3333
+ ". Found type: " + message.getClass() + ".";
3434
return new FlushReadyWrite(context, (ByteBuffer[]) message, listener);

libs/elasticsearch-nio/src/main/java/org/elasticsearch/nio/ChannelContext.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,12 @@
1919

2020
package org.elasticsearch.nio;
2121

22+
import org.elasticsearch.common.concurrent.CompletableContext;
23+
2224
import java.io.IOException;
2325
import java.nio.channels.NetworkChannel;
2426
import java.nio.channels.SelectableChannel;
2527
import java.nio.channels.SelectionKey;
26-
import java.util.concurrent.CompletableFuture;
2728
import java.util.function.BiConsumer;
2829
import java.util.function.Consumer;
2930

@@ -37,7 +38,7 @@ public abstract class ChannelContext<S extends SelectableChannel & NetworkChanne
3738

3839
protected final S rawChannel;
3940
private final Consumer<Exception> exceptionHandler;
40-
private final CompletableFuture<Void> closeContext = new CompletableFuture<>();
41+
private final CompletableContext<Void> closeContext = new CompletableContext<>();
4142
private volatile SelectionKey selectionKey;
4243

4344
ChannelContext(S rawChannel, Consumer<Exception> exceptionHandler) {
@@ -81,8 +82,8 @@ public void closeFromSelector() throws IOException {
8182
*
8283
* @param listener to be called
8384
*/
84-
public void addCloseListener(BiConsumer<Void, Throwable> listener) {
85-
closeContext.whenComplete(listener);
85+
public void addCloseListener(BiConsumer<Void, Exception> listener) {
86+
closeContext.addListener(listener);
8687
}
8788

8889
public boolean isOpen() {

libs/elasticsearch-nio/src/main/java/org/elasticsearch/nio/FlushOperation.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,13 @@
2525

2626
public class FlushOperation {
2727

28-
private final BiConsumer<Void, Throwable> listener;
28+
private final BiConsumer<Void, Exception> listener;
2929
private final ByteBuffer[] buffers;
3030
private final int[] offsets;
3131
private final int length;
3232
private int internalIndex;
3333

34-
public FlushOperation(ByteBuffer[] buffers, BiConsumer<Void, Throwable> listener) {
34+
public FlushOperation(ByteBuffer[] buffers, BiConsumer<Void, Exception> listener) {
3535
this.listener = listener;
3636
this.buffers = buffers;
3737
this.offsets = new int[buffers.length];
@@ -44,7 +44,7 @@ public FlushOperation(ByteBuffer[] buffers, BiConsumer<Void, Throwable> listener
4444
length = offset;
4545
}
4646

47-
public BiConsumer<Void, Throwable> getListener() {
47+
public BiConsumer<Void, Exception> getListener() {
4848
return listener;
4949
}
5050

libs/elasticsearch-nio/src/main/java/org/elasticsearch/nio/FlushReadyWrite.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ public class FlushReadyWrite extends FlushOperation implements WriteOperation {
2727
private final SocketChannelContext channelContext;
2828
private final ByteBuffer[] buffers;
2929

30-
FlushReadyWrite(SocketChannelContext channelContext, ByteBuffer[] buffers, BiConsumer<Void, Throwable> listener) {
30+
FlushReadyWrite(SocketChannelContext channelContext, ByteBuffer[] buffers, BiConsumer<Void, Exception> listener) {
3131
super(buffers, listener);
3232
this.channelContext = channelContext;
3333
this.buffers = buffers;

libs/elasticsearch-nio/src/main/java/org/elasticsearch/nio/NioChannel.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ public InetSocketAddress getLocalAddress() {
5353
*
5454
* @param listener to be called at close
5555
*/
56-
public void addCloseListener(BiConsumer<Void, Throwable> listener) {
56+
public void addCloseListener(BiConsumer<Void, Exception> listener) {
5757
getContext().addCloseListener(listener);
5858
}
5959

libs/elasticsearch-nio/src/main/java/org/elasticsearch/nio/NioSocketChannel.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ public InetSocketAddress getRemoteAddress() {
6060
return remoteAddress;
6161
}
6262

63-
public void addConnectListener(BiConsumer<Void, Throwable> listener) {
63+
public void addConnectListener(BiConsumer<Void, Exception> listener) {
6464
context.addConnectListener(listener);
6565
}
6666

libs/elasticsearch-nio/src/main/java/org/elasticsearch/nio/ReadWriteHandler.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ public interface ReadWriteHandler {
3838
* @param listener the listener to be called when the message is sent
3939
* @return the write operation to be queued
4040
*/
41-
WriteOperation createWriteOperation(SocketChannelContext context, Object message, BiConsumer<Void, Throwable> listener);
41+
WriteOperation createWriteOperation(SocketChannelContext context, Object message, BiConsumer<Void, Exception> listener);
4242

4343
/**
4444
* This method is called on the event loop thread. It should serialize a write operation object to bytes

libs/elasticsearch-nio/src/main/java/org/elasticsearch/nio/SocketChannelContext.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
package org.elasticsearch.nio;
2121

22+
import org.elasticsearch.common.concurrent.CompletableContext;
2223
import org.elasticsearch.nio.utils.ExceptionsHelper;
2324

2425
import java.io.IOException;
@@ -27,7 +28,6 @@
2728
import java.nio.channels.SocketChannel;
2829
import java.util.ArrayList;
2930
import java.util.LinkedList;
30-
import java.util.concurrent.CompletableFuture;
3131
import java.util.concurrent.atomic.AtomicBoolean;
3232
import java.util.function.BiConsumer;
3333
import java.util.function.Consumer;
@@ -48,7 +48,7 @@ public abstract class SocketChannelContext extends ChannelContext<SocketChannel>
4848
protected final AtomicBoolean isClosing = new AtomicBoolean(false);
4949
private final ReadWriteHandler readWriteHandler;
5050
private final SocketSelector selector;
51-
private final CompletableFuture<Void> connectContext = new CompletableFuture<>();
51+
private final CompletableContext<Void> connectContext = new CompletableContext<>();
5252
private final LinkedList<FlushOperation> pendingFlushes = new LinkedList<>();
5353
private boolean ioException;
5454
private boolean peerClosed;
@@ -73,8 +73,8 @@ public NioSocketChannel getChannel() {
7373
return channel;
7474
}
7575

76-
public void addConnectListener(BiConsumer<Void, Throwable> listener) {
77-
connectContext.whenComplete(listener);
76+
public void addConnectListener(BiConsumer<Void, Exception> listener) {
77+
connectContext.addListener(listener);
7878
}
7979

8080
public boolean isConnectComplete() {
@@ -121,7 +121,7 @@ public boolean connect() throws IOException {
121121
return isConnected;
122122
}
123123

124-
public void sendMessage(Object message, BiConsumer<Void, Throwable> listener) {
124+
public void sendMessage(Object message, BiConsumer<Void, Exception> listener) {
125125
if (isClosing.get()) {
126126
listener.accept(null, new ClosedChannelException());
127127
return;

0 commit comments

Comments
 (0)