io.reactivex.netty.client.RxClientImpl Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of rx-netty Show documentation
Show all versions of rx-netty Show documentation
rx-netty developed by Netflix
/*
* Copyright 2014 Netflix, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.reactivex.netty.client;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelInitializer;
import io.reactivex.netty.channel.ObservableConnection;
import io.reactivex.netty.metrics.MetricEventsListener;
import io.reactivex.netty.metrics.MetricEventsSubject;
import io.reactivex.netty.pipeline.PipelineConfigurator;
import io.reactivex.netty.pipeline.PipelineConfigurators;
import rx.Observable;
import rx.Observable.OnSubscribe;
import rx.Subscriber;
import rx.Subscription;
import java.util.concurrent.atomic.AtomicBoolean;
/**
* The base class for all connection oriented clients inside RxNetty.
*
* @param The request object type for this client.
* @param The response object type for this client.
*/
public class RxClientImpl implements RxClient {
protected final String name;
protected final ServerInfo serverInfo;
protected final Bootstrap clientBootstrap;
protected final PipelineConfigurator pipelineConfigurator;
protected final ClientChannelFactory channelFactory;
protected final ClientConnectionFactory> connectionFactory;
protected final ClientConfig clientConfig;
protected final MetricEventsSubject> eventsSubject;
protected final ConnectionPool pool;
private final AtomicBoolean isShutdown = new AtomicBoolean();
public RxClientImpl(String name, ServerInfo serverInfo, Bootstrap clientBootstrap,
PipelineConfigurator pipelineConfigurator,
ClientConfig clientConfig, ClientChannelFactory channelFactory,
ClientConnectionFactory> connectionFactory,
MetricEventsSubject> eventsSubject) {
if (null == name) {
throw new NullPointerException("Name can not be null.");
}
if (null == clientBootstrap) {
throw new NullPointerException("Client bootstrap can not be null.");
}
if (null == serverInfo) {
throw new NullPointerException("Server info can not be null.");
}
if (null == clientConfig) {
throw new NullPointerException("Client config can not be null.");
}
if (null == connectionFactory) {
throw new NullPointerException("Connection factory can not be null.");
}
if (null == channelFactory) {
throw new NullPointerException("Channel factory can not be null.");
}
this.name = name;
pool = null;
this.eventsSubject = eventsSubject;
this.clientConfig = clientConfig;
this.serverInfo = serverInfo;
this.clientBootstrap = clientBootstrap;
this.connectionFactory = connectionFactory;
this.connectionFactory.useMetricEventsSubject(eventsSubject);
this.channelFactory = channelFactory;
this.channelFactory.useMetricEventsSubject(eventsSubject);
this.pipelineConfigurator = pipelineConfigurator;
final PipelineConfigurator configurator = adaptPipelineConfigurator(pipelineConfigurator, clientConfig,
eventsSubject);
this.clientBootstrap.handler(new ChannelInitializer() {
@Override
public void initChannel(Channel ch) throws Exception {
configurator.configureNewPipeline(ch.pipeline());
}
});
}
public RxClientImpl(String name, ServerInfo serverInfo, Bootstrap clientBootstrap,
PipelineConfigurator pipelineConfigurator,
ClientConfig clientConfig, ConnectionPoolBuilder poolBuilder,
MetricEventsSubject> eventsSubject) {
if (null == name) {
throw new NullPointerException("Name can not be null.");
}
if (null == clientBootstrap) {
throw new NullPointerException("Client bootstrap can not be null.");
}
if (null == serverInfo) {
throw new NullPointerException("Server info can not be null.");
}
if (null == clientConfig) {
throw new NullPointerException("Client config can not be null.");
}
if (null == poolBuilder) {
throw new NullPointerException("Pool builder can not be null.");
}
this.name = name;
this.eventsSubject = eventsSubject;
this.clientConfig = clientConfig;
this.serverInfo = serverInfo;
this.clientBootstrap = clientBootstrap;
this.pipelineConfigurator = pipelineConfigurator;
final PipelineConfigurator configurator = adaptPipelineConfigurator(pipelineConfigurator, clientConfig,
eventsSubject);
this.clientBootstrap.handler(new ChannelInitializer() {
@Override
public void initChannel(Channel ch) throws Exception {
configurator.configureNewPipeline(ch.pipeline());
}
});
pool = poolBuilder.build();
channelFactory = poolBuilder.getChannelFactory();
connectionFactory = poolBuilder.getConnectionFactory();
}
/**
* A lazy connect to the {@link RxClient.ServerInfo} for this client. Every subscription to the returned {@link Observable}
* will create a fresh connection.
*
* @return Observable for the connect. Every new subscription will create a fresh connection.
*/
@Override
public Observable> connect() {
if (isShutdown.get()) {
return Observable.error(new IllegalStateException("Client is already shutdown."));
}
Observable> toReturn;
if (null != pool) {
toReturn = pool.acquire();
} else {
toReturn = Observable.create(new OnSubscribe>() {
@Override
public void call(final Subscriber super ObservableConnection> subscriber) {
try {
channelFactory.connect(subscriber, serverInfo, connectionFactory);
} catch (Throwable throwable) {
subscriber.onError(throwable);
}
}
});
}
return toReturn.take(1); // We only need one connection, even if the underlying source emits multiple.
}
@Override
public void shutdown() {
if (!isShutdown.compareAndSet(false, true)) {
return;
}
if (null != pool) {
pool.shutdown();
}
}
@Override
public String name() {
return name;
}
protected PipelineConfigurator adaptPipelineConfigurator(PipelineConfigurator pipelineConfigurator,
ClientConfig clientConfig,
MetricEventsSubject> eventsSubject) {
return PipelineConfigurators.createClientConfigurator(pipelineConfigurator, clientConfig, eventsSubject);
}
@Override
public Subscription subscribe(MetricEventsListener extends ClientMetricsEvent>> listener) {
return eventsSubject.subscribe(listener);
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy