Update reactor2 support
This commit is contained in:
committed by
Rossen Stoyanchev
parent
5ebc1a8b60
commit
7891c0d5ca
@@ -29,14 +29,17 @@ import reactor.core.config.ConfigurationReader;
|
|||||||
import reactor.core.config.DispatcherConfiguration;
|
import reactor.core.config.DispatcherConfiguration;
|
||||||
import reactor.core.config.ReactorConfiguration;
|
import reactor.core.config.ReactorConfiguration;
|
||||||
import reactor.core.support.NamedDaemonThreadFactory;
|
import reactor.core.support.NamedDaemonThreadFactory;
|
||||||
import reactor.fn.BiFunction;
|
|
||||||
import reactor.fn.Consumer;
|
import reactor.fn.Consumer;
|
||||||
import reactor.fn.Function;
|
import reactor.fn.Function;
|
||||||
import reactor.fn.tuple.Tuple;
|
import reactor.fn.tuple.Tuple;
|
||||||
import reactor.fn.tuple.Tuple2;
|
import reactor.fn.tuple.Tuple2;
|
||||||
import reactor.io.buffer.Buffer;
|
import reactor.io.buffer.Buffer;
|
||||||
import reactor.io.codec.Codec;
|
import reactor.io.codec.Codec;
|
||||||
import reactor.io.net.*;
|
import reactor.io.net.ChannelStream;
|
||||||
|
import reactor.io.net.NetStreams;
|
||||||
|
import reactor.io.net.NetStreams.TcpClientFactory;
|
||||||
|
import reactor.io.net.ReactorChannelHandler;
|
||||||
|
import reactor.io.net.Reconnect;
|
||||||
import reactor.io.net.Spec.TcpClientSpec;
|
import reactor.io.net.Spec.TcpClientSpec;
|
||||||
import reactor.io.net.impl.netty.NettyClientSocketOptions;
|
import reactor.io.net.impl.netty.NettyClientSocketOptions;
|
||||||
import reactor.io.net.impl.netty.tcp.NettyTcpClient;
|
import reactor.io.net.impl.netty.tcp.NettyTcpClient;
|
||||||
@@ -71,7 +74,7 @@ public class Reactor2TcpClient<P> implements TcpOperations<P> {
|
|||||||
@SuppressWarnings("rawtypes")
|
@SuppressWarnings("rawtypes")
|
||||||
public static final Class<NettyTcpClient> REACTOR_TCP_CLIENT_TYPE = NettyTcpClient.class;
|
public static final Class<NettyTcpClient> REACTOR_TCP_CLIENT_TYPE = NettyTcpClient.class;
|
||||||
|
|
||||||
private final NetStreams.TcpClientFactory<Message<P>, Message<P>> tcpClientSpecFactory;
|
private final TcpClientFactory<Message<P>, Message<P>> tcpClientSpecFactory;
|
||||||
|
|
||||||
private final List<TcpClient<Message<P>, Message<P>>> tcpClients =
|
private final List<TcpClient<Message<P>, Message<P>>> tcpClients =
|
||||||
new ArrayList<TcpClient<Message<P>, Message<P>>>();
|
new ArrayList<TcpClient<Message<P>, Message<P>>>();
|
||||||
@@ -94,7 +97,7 @@ public class Reactor2TcpClient<P> implements TcpOperations<P> {
|
|||||||
|
|
||||||
final NioEventLoopGroup eventLoopGroup = initEventLoopGroup();
|
final NioEventLoopGroup eventLoopGroup = initEventLoopGroup();
|
||||||
|
|
||||||
this.tcpClientSpecFactory = new NetStreams.TcpClientFactory<Message<P>, Message<P>>() {
|
this.tcpClientSpecFactory = new TcpClientFactory<Message<P>, Message<P>>() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TcpClientSpec<Message<P>, Message<P>> apply(TcpClientSpec<Message<P>, Message<P>> spec) {
|
public TcpClientSpec<Message<P>, Message<P>> apply(TcpClientSpec<Message<P>, Message<P>> spec) {
|
||||||
@@ -111,7 +114,8 @@ public class Reactor2TcpClient<P> implements TcpOperations<P> {
|
|||||||
int ioThreadCount;
|
int ioThreadCount;
|
||||||
try {
|
try {
|
||||||
ioThreadCount = Integer.parseInt(System.getProperty("reactor.tcp.ioThreadCount"));
|
ioThreadCount = Integer.parseInt(System.getProperty("reactor.tcp.ioThreadCount"));
|
||||||
} catch (Exception i) {
|
}
|
||||||
|
catch (Exception i) {
|
||||||
ioThreadCount = -1;
|
ioThreadCount = -1;
|
||||||
}
|
}
|
||||||
if (ioThreadCount <= 0l) {
|
if (ioThreadCount <= 0l) {
|
||||||
@@ -132,20 +136,16 @@ public class Reactor2TcpClient<P> implements TcpOperations<P> {
|
|||||||
*
|
*
|
||||||
* @param tcpClientSpecFactory the TcpClientSpec {@link Function} to use for each client creation.
|
* @param tcpClientSpecFactory the TcpClientSpec {@link Function} to use for each client creation.
|
||||||
*/
|
*/
|
||||||
public Reactor2TcpClient(NetStreams.TcpClientFactory<Message<P>, Message<P>> tcpClientSpecFactory) {
|
public Reactor2TcpClient(TcpClientFactory<Message<P>, Message<P>> tcpClientSpecFactory) {
|
||||||
Assert.notNull(tcpClientSpecFactory, "'tcpClientClientFactory' must not be null");
|
Assert.notNull(tcpClientSpecFactory, "'tcpClientClientFactory' must not be null");
|
||||||
this.tcpClientSpecFactory = tcpClientSpecFactory;
|
this.tcpClientSpecFactory = tcpClientSpecFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ListenableFuture<Void> connect(TcpConnectionHandler<P> connectionHandler) {
|
public ListenableFuture<Void> connect(final TcpConnectionHandler<P> connectionHandler) {
|
||||||
Class<NettyTcpClient> type = REACTOR_TCP_CLIENT_TYPE;
|
Assert.notNull(connectionHandler, "'connectionHandler' must not be null");
|
||||||
|
Promise<Void> promise = createTcpClient().start(new MessageChannelStreamHandler<P>(connectionHandler));
|
||||||
TcpClient<Message<P>, Message<P>> tcpClient = NetStreams.tcpClient(type, this.tcpClientSpecFactory);
|
|
||||||
|
|
||||||
Promise<Void> promise = tcpClient.start(composeConnectionHandling(tcpClient, connectionHandler));
|
|
||||||
|
|
||||||
return new PassThroughPromiseToListenableFutureAdapter<Void>(
|
return new PassThroughPromiseToListenableFutureAdapter<Void>(
|
||||||
promise.onError(new Consumer<Throwable>() {
|
promise.onError(new Consumer<Throwable>() {
|
||||||
@Override
|
@Override
|
||||||
@@ -157,72 +157,33 @@ public class Reactor2TcpClient<P> implements TcpOperations<P> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ListenableFuture<Void> connect(TcpConnectionHandler<P> handler, ReconnectStrategy strategy) {
|
public ListenableFuture<Void> connect(TcpConnectionHandler<P> connectionHandler, ReconnectStrategy strategy) {
|
||||||
Assert.notNull(strategy, "ReconnectStrategy must not be null");
|
Assert.notNull(connectionHandler, "'connectionHandler' must not be null");
|
||||||
Class<NettyTcpClient> type = REACTOR_TCP_CLIENT_TYPE;
|
Assert.notNull(strategy, "'reconnectStrategy' must not be null");
|
||||||
|
|
||||||
TcpClient<Message<P>, Message<P>> tcpClient = NetStreams.tcpClient(type, this.tcpClientSpecFactory);
|
Stream<Tuple2<InetSocketAddress, Integer>> stream = createTcpClient().start(
|
||||||
|
new MessageChannelStreamHandler<P>(connectionHandler),
|
||||||
Stream<Tuple2<InetSocketAddress, Integer>> stream = tcpClient.start(
|
new ReactorReconnectAdapter(strategy));
|
||||||
composeConnectionHandling(tcpClient, handler),
|
|
||||||
new ReactorRectonnectAdapter(strategy)
|
|
||||||
);
|
|
||||||
|
|
||||||
return new PassThroughPromiseToListenableFutureAdapter<Void>(stream.next().after());
|
return new PassThroughPromiseToListenableFutureAdapter<Void>(stream.next().after());
|
||||||
}
|
}
|
||||||
|
|
||||||
private MessageHandler<P> composeConnectionHandling(
|
private TcpClient<Message<P>, Message<P>> createTcpClient() {
|
||||||
final TcpClient<Message<P>, Message<P>> tcpClient,
|
Class<NettyTcpClient> type = REACTOR_TCP_CLIENT_TYPE;
|
||||||
final TcpConnectionHandler<P> connectionHandler
|
TcpClient<Message<P>, Message<P>> tcpClient = NetStreams.tcpClient(type, this.tcpClientSpecFactory);
|
||||||
) {
|
|
||||||
|
|
||||||
synchronized (this.tcpClients) {
|
synchronized (this.tcpClients) {
|
||||||
this.tcpClients.add(tcpClient);
|
this.tcpClients.add(tcpClient);
|
||||||
}
|
}
|
||||||
|
return tcpClient;
|
||||||
return new MessageHandler<P>() {
|
|
||||||
@Override
|
|
||||||
public Publisher<Void> apply(ChannelStream<Message<P>, Message<P>> connection) {
|
|
||||||
|
|
||||||
Promise<Void> closePromise = Promises.prepare();
|
|
||||||
|
|
||||||
connectionHandler.afterConnected(new Reactor2TcpConnection<P>(connection, closePromise));
|
|
||||||
|
|
||||||
connection
|
|
||||||
.finallyDo(new Consumer<Signal<Message<P>>>() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void accept(Signal<Message<P>> signal) {
|
|
||||||
if (signal.isOnError()) {
|
|
||||||
connectionHandler.handleFailure(signal.getThrowable());
|
|
||||||
} else if (signal.isOnComplete()) {
|
|
||||||
connectionHandler.afterConnectionClosed();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.consume(new Consumer<Message<P>>() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void accept(Message<P> message) {
|
|
||||||
connectionHandler.handleMessage(message);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return closePromise;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ListenableFuture<Void> shutdown() {
|
public ListenableFuture<Void> shutdown() {
|
||||||
|
final List<TcpClient<Message<P>, Message<P>>> readOnlyClients;
|
||||||
final List<TcpClient<Message<P>, Message<P>>> clients;
|
|
||||||
|
|
||||||
synchronized (this.tcpClients) {
|
synchronized (this.tcpClients) {
|
||||||
clients = new ArrayList<TcpClient<Message<P>, Message<P>>>(this.tcpClients);
|
readOnlyClients = new ArrayList<TcpClient<Message<P>, Message<P>>>(this.tcpClients);
|
||||||
}
|
}
|
||||||
|
Promise<Void> promise = Streams.from(readOnlyClients)
|
||||||
Promise<Void> promise = Streams.from(clients)
|
|
||||||
.flatMap(new Function<TcpClient<Message<P>, Message<P>>, Promise<Void>>() {
|
.flatMap(new Function<TcpClient<Message<P>, Message<P>>, Promise<Void>>() {
|
||||||
@Override
|
@Override
|
||||||
public Promise<Void> apply(final TcpClient<Message<P>, Message<P>> client) {
|
public Promise<Void> apply(final TcpClient<Message<P>, Message<P>> client) {
|
||||||
@@ -237,10 +198,10 @@ public class Reactor2TcpClient<P> implements TcpOperations<P> {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
.next();
|
.next();
|
||||||
|
|
||||||
return new PassThroughPromiseToListenableFutureAdapter<Void>(promise);
|
return new PassThroughPromiseToListenableFutureAdapter<Void>(promise);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static class SynchronousDispatcherConfigReader implements ConfigurationReader {
|
private static class SynchronousDispatcherConfigReader implements ConfigurationReader {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -249,11 +210,52 @@ public class Reactor2TcpClient<P> implements TcpOperations<P> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class ReactorRectonnectAdapter implements Reconnect {
|
private static class MessageChannelStreamHandler<P>
|
||||||
|
implements ReactorChannelHandler<Message<P>, Message<P>, ChannelStream<Message<P>, Message<P>>> {
|
||||||
|
|
||||||
|
private final TcpConnectionHandler<P> connectionHandler;
|
||||||
|
|
||||||
|
public MessageChannelStreamHandler(TcpConnectionHandler<P> connectionHandler) {
|
||||||
|
this.connectionHandler = connectionHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Publisher<Void> apply(ChannelStream<Message<P>, Message<P>> channelStream) {
|
||||||
|
|
||||||
|
Promise<Void> closePromise = Promises.prepare();
|
||||||
|
|
||||||
|
this.connectionHandler.afterConnected(new Reactor2TcpConnection<P>(channelStream, closePromise));
|
||||||
|
|
||||||
|
channelStream
|
||||||
|
.finallyDo(new Consumer<Signal<Message<P>>>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void accept(Signal<Message<P>> signal) {
|
||||||
|
if (signal.isOnError()) {
|
||||||
|
connectionHandler.handleFailure(signal.getThrowable());
|
||||||
|
}
|
||||||
|
else if (signal.isOnComplete()) {
|
||||||
|
connectionHandler.afterConnectionClosed();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.consume(new Consumer<Message<P>>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void accept(Message<P> message) {
|
||||||
|
connectionHandler.handleMessage(message);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return closePromise;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class ReactorReconnectAdapter implements Reconnect {
|
||||||
|
|
||||||
private final ReconnectStrategy strategy;
|
private final ReconnectStrategy strategy;
|
||||||
|
|
||||||
public ReactorRectonnectAdapter(ReconnectStrategy strategy) {
|
public ReactorReconnectAdapter(ReconnectStrategy strategy) {
|
||||||
this.strategy = strategy;
|
this.strategy = strategy;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -261,11 +263,6 @@ public class Reactor2TcpClient<P> implements TcpOperations<P> {
|
|||||||
public Tuple2<InetSocketAddress, Long> reconnect(InetSocketAddress address, int attempt) {
|
public Tuple2<InetSocketAddress, Long> reconnect(InetSocketAddress address, int attempt) {
|
||||||
return Tuple.of(address, strategy.getTimeToNextAttempt(attempt));
|
return Tuple.of(address, strategy.getTimeToNextAttempt(attempt));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private interface MessageHandler<P>
|
|
||||||
extends ReactorChannelHandler<Message<P>, Message<P>, ChannelStream<Message<P>, Message<P>>>{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,15 +16,11 @@
|
|||||||
|
|
||||||
package org.springframework.messaging.tcp.reactor;
|
package org.springframework.messaging.tcp.reactor;
|
||||||
|
|
||||||
import org.reactivestreams.Subscriber;
|
|
||||||
import org.reactivestreams.Subscription;
|
|
||||||
import org.springframework.util.concurrent.ListenableFutureAdapter;
|
|
||||||
import reactor.fn.Functions;
|
import reactor.fn.Functions;
|
||||||
import reactor.io.net.ChannelStream;
|
import reactor.io.net.ChannelStream;
|
||||||
import reactor.rx.Promise;
|
import reactor.rx.Promise;
|
||||||
import reactor.rx.Promises;
|
import reactor.rx.Promises;
|
||||||
import reactor.rx.Streams;
|
import reactor.rx.Streams;
|
||||||
import reactor.rx.broadcast.Broadcaster;
|
|
||||||
|
|
||||||
import org.springframework.messaging.Message;
|
import org.springframework.messaging.Message;
|
||||||
import org.springframework.messaging.tcp.TcpConnection;
|
import org.springframework.messaging.tcp.TcpConnection;
|
||||||
@@ -42,9 +38,13 @@ import org.springframework.util.concurrent.ListenableFuture;
|
|||||||
public class Reactor2TcpConnection<P> implements TcpConnection<P> {
|
public class Reactor2TcpConnection<P> implements TcpConnection<P> {
|
||||||
|
|
||||||
private final ChannelStream<Message<P>, Message<P>> channelStream;
|
private final ChannelStream<Message<P>, Message<P>> channelStream;
|
||||||
|
|
||||||
private final Promise<Void> closePromise;
|
private final Promise<Void> closePromise;
|
||||||
|
|
||||||
public Reactor2TcpConnection(ChannelStream<Message<P>, Message<P>> channelStream, Promise<Void> closePromise) {
|
|
||||||
|
public Reactor2TcpConnection(ChannelStream<Message<P>, Message<P>> channelStream,
|
||||||
|
Promise<Void> closePromise) {
|
||||||
|
|
||||||
this.channelStream = channelStream;
|
this.channelStream = channelStream;
|
||||||
this.closePromise = closePromise;
|
this.closePromise = closePromise;
|
||||||
}
|
}
|
||||||
@@ -71,4 +71,5 @@ public class Reactor2TcpConnection<P> implements TcpConnection<P> {
|
|||||||
public void close() {
|
public void close() {
|
||||||
this.closePromise.onComplete();
|
this.closePromise.onComplete();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user