Skip to content

Commit be0e2bf

Browse files
committed
Add constructor for SdkEventLoopGroup
1 parent fb7ee37 commit be0e2bf

File tree

3 files changed

+106
-23
lines changed

3 files changed

+106
-23
lines changed

http-clients/netty-nio-client/src/main/java/software/amazon/awssdk/http/nio/netty/SdkEventLoopGroup.java

Lines changed: 38 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
/**
3535
* Provides {@link EventLoopGroup} and {@link ChannelFactory} for {@link NettyNioAsyncHttpClient}.
3636
* <p>
37-
* There are three ways to create a new instance.
37+
* There are four ways to create a new instance.
3838
*
3939
* <ul>
4040
* <li>using {@link #builder()} to provide custom configuration of {@link EventLoopGroup}.
@@ -49,6 +49,9 @@
4949
*
5050
* <li>Using {@link #create(EventLoopGroup, ChannelFactory)} to provide a custom {@link EventLoopGroup} and
5151
* {@link ChannelFactory}
52+
*
53+
* <li>Using {@link #create(EventLoopGroup, ChannelFactory, ChannelFactory)} to provide a custom {@link EventLoopGroup}, and
54+
* socket and datagram {@link ChannelFactory}'s.
5255
* </ul>
5356
*
5457
* <p>
@@ -78,6 +81,16 @@ public final class SdkEventLoopGroup {
7881
this.datagramChannelFactory = ChannelResolver.resolveDatagramChannelFactory(eventLoopGroup);
7982
}
8083

84+
SdkEventLoopGroup(EventLoopGroup eventLoopGroup, ChannelFactory<? extends Channel> socketChannelFactory,
85+
ChannelFactory<? extends DatagramChannel> datagramChannelFactory) {
86+
Validate.paramNotNull(eventLoopGroup, "eventLoopGroup");
87+
Validate.paramNotNull(socketChannelFactory, "socketChannelFactory");
88+
Validate.paramNotNull(datagramChannelFactory, "datagramChannelFactory");
89+
this.eventLoopGroup = eventLoopGroup;
90+
this.channelFactory = socketChannelFactory;
91+
this.datagramChannelFactory = datagramChannelFactory;
92+
}
93+
8194
/**
8295
* Create an instance of {@link SdkEventLoopGroup} from the builder
8396
*/
@@ -109,15 +122,30 @@ public ChannelFactory<? extends DatagramChannel> datagramChannelFactory() {
109122
}
110123

111124
/**
112-
* Creates a new instance of SdkEventLoopGroup with {@link EventLoopGroup} and {@link ChannelFactory}
125+
* Creates a new instance of SdkEventLoopGroup with {@link EventLoopGroup} and socket {@link ChannelFactory}
113126
* to be used with {@link NettyNioAsyncHttpClient}.
114127
*
115128
* @param eventLoopGroup the EventLoopGroup to be used
116-
* @param channelFactory the channel factor to be used
129+
* @param socketChannelFactory the socket channel factory to be used
117130
* @return a new instance of SdkEventLoopGroup
118131
*/
119-
public static SdkEventLoopGroup create(EventLoopGroup eventLoopGroup, ChannelFactory<? extends Channel> channelFactory) {
120-
return new SdkEventLoopGroup(eventLoopGroup, channelFactory);
132+
public static SdkEventLoopGroup create(EventLoopGroup eventLoopGroup,
133+
ChannelFactory<? extends Channel> socketChannelFactory) {
134+
return new SdkEventLoopGroup(eventLoopGroup, socketChannelFactory);
135+
}
136+
137+
/**
138+
* Creates a new instance of SdkEventLoopGroup with {@link EventLoopGroup}, and socket and datagram
139+
* {@link ChannelFactory}'s to be used with {@link NettyNioAsyncHttpClient}.
140+
*
141+
* @param eventLoopGroup the EventLoopGroup to be used
142+
* @param socketChannelFactory the socket channel factory to be used
143+
* @param datagramChannelFactory the datagram channel factory to be used
144+
* @return a new instance of SdkEventLoopGroup
145+
*/
146+
public static SdkEventLoopGroup create(EventLoopGroup eventLoopGroup, ChannelFactory<? extends Channel> socketChannelFactory,
147+
ChannelFactory<? extends DatagramChannel> datagramChannelFactory) {
148+
return new SdkEventLoopGroup(eventLoopGroup, socketChannelFactory, datagramChannelFactory);
121149
}
122150

123151
/**
@@ -128,8 +156,11 @@ public static SdkEventLoopGroup create(EventLoopGroup eventLoopGroup, ChannelFac
128156
* be thrown for any unknown EventLoopGroup type.
129157
* <p>
130158
* If {@link MultiThreadIoEventLoopGroup} is passed in, {@link NioSocketChannel} and {@link NioDatagramChannel} will be
131-
* resolved, regardless of the transport {@link IoHandlerFactory} passed in. This is because it is not possible to
132-
* determine the type of transport factory from a given {@link MultiThreadIoEventLoopGroup}.
159+
* resolved, regardless of the transport {@link IoHandlerFactory} set on the {@link MultiThreadIoEventLoopGroup}. This is
160+
* because it is not possible to determine the type of transport factory from a given {@link MultiThreadIoEventLoopGroup}.
161+
* <p>
162+
* To use a {@link MultiThreadIoEventLoopGroup} with a non-Nio transport factory, use
163+
* {@link #create(EventLoopGroup, ChannelFactory, ChannelFactory)}, specifying the socket and datagram channels.
133164
*
134165
* @param eventLoopGroup the EventLoopGroup to be used
135166
* @return a new instance of SdkEventLoopGroup

http-clients/netty-nio-client/src/main/java/software/amazon/awssdk/http/nio/netty/internal/utils/ChannelResolver.java

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import io.netty.channel.epoll.EpollDatagramChannel;
2626
import io.netty.channel.epoll.EpollEventLoopGroup;
2727
import io.netty.channel.epoll.EpollSocketChannel;
28+
import io.netty.channel.nio.NioEventLoopGroup;
2829
import io.netty.channel.socket.DatagramChannel;
2930
import io.netty.channel.socket.nio.NioDatagramChannel;
3031
import io.netty.channel.socket.nio.NioSocketChannel;
@@ -67,19 +68,25 @@ public static ChannelFactory<? extends Channel> resolveSocketChannelFactory(Even
6768
return resolveSocketChannelFactory(((DelegatingEventLoopGroup) eventLoopGroup).getDelegate());
6869
}
6970

71+
if (eventLoopGroup instanceof NioEventLoopGroup) {
72+
return NioSocketChannel::new;
73+
}
7074
if (eventLoopGroup instanceof EpollEventLoopGroup) {
7175
return EpollSocketChannel::new;
7276
}
73-
if (eventLoopGroup instanceof MultiThreadIoEventLoopGroup) {
74-
return NioSocketChannel::new;
75-
}
7677

7778
String socketFqcn = KNOWN_EL_GROUPS_SOCKET_CHANNELS.get(eventLoopGroup.getClass().getName());
78-
if (socketFqcn == null) {
79-
throw new IllegalArgumentException("Unknown event loop group : " + eventLoopGroup.getClass());
79+
if (socketFqcn != null) {
80+
return invokeSafely(() -> new ReflectiveChannelFactory(Class.forName(socketFqcn)));
81+
}
82+
83+
// The old deprecated transport-specific event loop groups all extend MultiThreadIoEventLoopGroup, so we have to do
84+
// this check last. It is not possible to determine the type of transport factory so we will default to Nio.
85+
if (eventLoopGroup instanceof MultiThreadIoEventLoopGroup) {
86+
return NioSocketChannel::new;
8087
}
8188

82-
return invokeSafely(() -> new ReflectiveChannelFactory(Class.forName(socketFqcn)));
89+
throw new IllegalArgumentException("Unknown event loop group : " + eventLoopGroup.getClass());
8390
}
8491

8592
/**
@@ -95,18 +102,24 @@ public static ChannelFactory<? extends DatagramChannel> resolveDatagramChannelFa
95102
return resolveDatagramChannelFactory(((DelegatingEventLoopGroup) eventLoopGroup).getDelegate());
96103
}
97104

105+
if (eventLoopGroup instanceof NioEventLoopGroup) {
106+
return NioDatagramChannel::new;
107+
}
98108
if (eventLoopGroup instanceof EpollEventLoopGroup) {
99109
return EpollDatagramChannel::new;
100110
}
101-
if (eventLoopGroup instanceof MultiThreadIoEventLoopGroup) {
102-
return NioDatagramChannel::new;
103-
}
104111

105112
String datagramFqcn = KNOWN_EL_GROUPS_DATAGRAM_CHANNELS.get(eventLoopGroup.getClass().getName());
106-
if (datagramFqcn == null) {
107-
throw new IllegalArgumentException("Unknown event loop group : " + eventLoopGroup.getClass());
113+
if (datagramFqcn != null) {
114+
return invokeSafely(() -> new ReflectiveChannelFactory(Class.forName(datagramFqcn)));
115+
}
116+
117+
// The old deprecated transport-specific event loop groups all extend MultiThreadIoEventLoopGroup, so we have to do
118+
// this check last. It is not possible to determine the type of transport factory so we will default to Nio.
119+
if (eventLoopGroup instanceof MultiThreadIoEventLoopGroup) {
120+
return NioDatagramChannel::new;
108121
}
109122

110-
return invokeSafely(() -> new ReflectiveChannelFactory(Class.forName(datagramFqcn)));
123+
throw new IllegalArgumentException("Unknown event loop group : " + eventLoopGroup.getClass());
111124
}
112125
}

http-clients/netty-nio-client/src/test/java/software/amazon/awssdk/http/nio/netty/SdkEventLoopGroupTest.java

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,18 +16,23 @@
1616
package software.amazon.awssdk.http.nio.netty;
1717

1818
import static org.assertj.core.api.Assertions.assertThat;
19+
import static org.junit.jupiter.api.Assertions.assertThrows;
1920

2021
import io.netty.channel.DefaultEventLoopGroup;
22+
import io.netty.channel.epoll.Epoll;
2123
import io.netty.channel.epoll.EpollDatagramChannel;
22-
import io.netty.channel.epoll.EpollEventLoopGroup;
24+
import io.netty.channel.epoll.EpollIoHandler;
2325
import io.netty.channel.epoll.EpollSocketChannel;
26+
import io.netty.channel.MultiThreadIoEventLoopGroup;
2427
import io.netty.channel.nio.NioEventLoopGroup;
28+
import io.netty.channel.nio.NioIoHandler;
2529
import io.netty.channel.oio.OioEventLoopGroup;
2630
import io.netty.channel.socket.nio.NioDatagramChannel;
2731
import io.netty.channel.socket.nio.NioSocketChannel;
2832
import io.netty.channel.socket.oio.OioDatagramChannel;
2933
import io.netty.channel.socket.oio.OioSocketChannel;
30-
import org.junit.Test;
34+
import org.junit.jupiter.api.Assumptions;
35+
import org.junit.jupiter.api.Test;
3136

3237
public class SdkEventLoopGroupTest {
3338

@@ -64,8 +69,42 @@ public void notProvidingChannelFactory_channelFactoryResolved() {
6469
assertThat(sdkEventLoopGroup.datagramChannelFactory().newChannel()).isInstanceOf(NioDatagramChannel.class);
6570
}
6671

67-
@Test(expected = IllegalArgumentException.class)
72+
@Test
73+
public void multiThreadIoEventLoopGroup_nioIoHandler_withoutChannelFactory() {
74+
SdkEventLoopGroup sdkEventLoopGroup =
75+
SdkEventLoopGroup.create(new MultiThreadIoEventLoopGroup(NioIoHandler.newFactory()));
76+
77+
assertThat(sdkEventLoopGroup.channelFactory().newChannel()).isInstanceOf(NioSocketChannel.class);
78+
assertThat(sdkEventLoopGroup.datagramChannelFactory().newChannel()).isInstanceOf(NioDatagramChannel.class);
79+
}
80+
81+
@Test
82+
public void multiThreadIoEventLoopGroupWithNonNioIoHandler_withoutChannelFactory_createsNioChannels() {
83+
Assumptions.assumeTrue(Epoll.isAvailable());
84+
85+
SdkEventLoopGroup sdkEventLoopGroup =
86+
SdkEventLoopGroup.create(new MultiThreadIoEventLoopGroup(EpollIoHandler.newFactory()));
87+
88+
assertThat(sdkEventLoopGroup.channelFactory().newChannel()).isInstanceOf(NioSocketChannel.class);
89+
assertThat(sdkEventLoopGroup.datagramChannelFactory().newChannel()).isInstanceOf(NioDatagramChannel.class);
90+
}
91+
92+
@Test
93+
public void multiThreadIoEventLoopGroupWithNonNioIoHandler_withChannelsFactories_properlySetsChannelTypes() {
94+
Assumptions.assumeTrue(Epoll.isAvailable());
95+
96+
SdkEventLoopGroup sdkEventLoopGroup =
97+
SdkEventLoopGroup.create(new MultiThreadIoEventLoopGroup(EpollIoHandler.newFactory()),
98+
EpollSocketChannel::new,
99+
EpollDatagramChannel::new);
100+
assertThat(sdkEventLoopGroup.channelFactory()).isNotNull();
101+
assertThat(sdkEventLoopGroup.channelFactory().newChannel()).isInstanceOf(EpollSocketChannel.class);
102+
assertThat(sdkEventLoopGroup.datagramChannelFactory().newChannel()).isInstanceOf(EpollDatagramChannel.class);
103+
assertThat(sdkEventLoopGroup.eventLoopGroup()).isNotNull();
104+
}
105+
106+
@Test
68107
public void notProvidingChannelFactory_unknownEventLoopGroup() {
69-
SdkEventLoopGroup.create(new DefaultEventLoopGroup());
108+
assertThrows(IllegalArgumentException.class, () -> SdkEventLoopGroup.create(new DefaultEventLoopGroup()));
70109
}
71110
}

0 commit comments

Comments
 (0)