mirror of https://github.com/grpc/grpc-java.git
[1/3] Move AbstractTransportTest to third_party.
This required making it no longer depend on GrpcClient. Instead, we now use the builders that make using GrpcClient almost completely obsolete. ------------- Created by MOE: http://code.google.com/p/moe-java MOE_MIGRATED_REVID=78860648
This commit is contained in:
parent
8b0b46eff5
commit
9a5a8de65d
|
|
@ -0,0 +1,382 @@
|
||||||
|
package com.google.net.stubby.testing.integration;
|
||||||
|
|
||||||
|
import static com.google.net.stubby.testing.integration.Messages.PayloadType.COMPRESSABLE;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
|
||||||
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
import com.google.common.util.concurrent.SettableFuture;
|
||||||
|
import com.google.common.util.concurrent.Uninterruptibles;
|
||||||
|
import com.google.net.stubby.Call;
|
||||||
|
import com.google.net.stubby.ChannelImpl;
|
||||||
|
import com.google.net.stubby.Metadata;
|
||||||
|
import com.google.net.stubby.Status;
|
||||||
|
import com.google.net.stubby.proto.ProtoUtils;
|
||||||
|
import com.google.net.stubby.stub.MetadataUtils;
|
||||||
|
import com.google.net.stubby.stub.StreamObserver;
|
||||||
|
import com.google.net.stubby.stub.StreamRecorder;
|
||||||
|
import com.google.net.stubby.testing.integration.Messages.PayloadType;
|
||||||
|
import com.google.net.stubby.testing.integration.Messages.SimpleRequest;
|
||||||
|
import com.google.net.stubby.testing.integration.Messages.SimpleResponse;
|
||||||
|
import com.google.net.stubby.testing.integration.Messages.StreamingInputCallRequest;
|
||||||
|
import com.google.net.stubby.testing.integration.Messages.StreamingInputCallResponse;
|
||||||
|
import com.google.net.stubby.testing.integration.Messages.StreamingOutputCallRequest;
|
||||||
|
import com.google.net.stubby.testing.integration.Messages.StreamingOutputCallResponse;
|
||||||
|
import com.google.net.stubby.transport.AbstractStream;
|
||||||
|
import com.google.protobuf.ByteString;
|
||||||
|
import com.google.protobuf.EmptyProtos.Empty;
|
||||||
|
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Assume;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Random;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Abstract base class for all GRPC transport tests.
|
||||||
|
*/
|
||||||
|
public abstract class AbstractTransportTest {
|
||||||
|
|
||||||
|
public static final Metadata.Key<Messages.SimpleContext> METADATA_KEY =
|
||||||
|
ProtoUtils.keyForProto(Messages.SimpleContext.getDefaultInstance());
|
||||||
|
|
||||||
|
protected ChannelImpl channel;
|
||||||
|
protected TestServiceGrpc.TestServiceBlockingStub blockingStub;
|
||||||
|
protected TestServiceGrpc.TestService asyncStub;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Must be called by the subclass setup method.
|
||||||
|
*/
|
||||||
|
@Before
|
||||||
|
public void setup() throws Exception {
|
||||||
|
channel = createChannel();
|
||||||
|
channel.startAsync();
|
||||||
|
channel.awaitRunning();
|
||||||
|
blockingStub = TestServiceGrpc.newBlockingStub(channel);
|
||||||
|
asyncStub = TestServiceGrpc.newStub(channel);
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void teardown() throws Exception {
|
||||||
|
if (channel != null) {
|
||||||
|
channel.stopAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract ChannelImpl createChannel();
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void emptyShouldSucceed() throws Exception {
|
||||||
|
Empty response = blockingStub.emptyCall(Empty.getDefaultInstance());
|
||||||
|
assertNotNull(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void unaryCallShouldSucceed() throws Exception {
|
||||||
|
// Create the request.
|
||||||
|
SimpleResponse response = blockingStub.unaryCall(unaryRequest());
|
||||||
|
assertNotNull(response);
|
||||||
|
assertEquals(COMPRESSABLE, response.getPayload().getType());
|
||||||
|
assertEquals(10, response.getPayload().getBody().size());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void streamingOutputCallShouldSucceed() throws Exception {
|
||||||
|
// Build the request.
|
||||||
|
List<Integer> responseSizes = Arrays.asList(50, 100, 150, 200);
|
||||||
|
StreamingOutputCallRequest.Builder streamingOutputBuilder =
|
||||||
|
StreamingOutputCallRequest.newBuilder();
|
||||||
|
streamingOutputBuilder.setResponseType(COMPRESSABLE);
|
||||||
|
for (Integer size : responseSizes) {
|
||||||
|
streamingOutputBuilder.addResponseParametersBuilder().setSize(size).setIntervalUs(0);
|
||||||
|
}
|
||||||
|
StreamingOutputCallRequest request = streamingOutputBuilder.build();
|
||||||
|
|
||||||
|
StreamRecorder<StreamingOutputCallResponse> recorder = StreamRecorder.create();
|
||||||
|
asyncStub.streamingOutputCall(request, recorder);
|
||||||
|
recorder.awaitCompletion();
|
||||||
|
assertSuccess(recorder);
|
||||||
|
assertEquals(responseSizes.size(), recorder.getValues().size());
|
||||||
|
for (int ix = 0; ix < recorder.getValues().size(); ++ix) {
|
||||||
|
StreamingOutputCallResponse response = recorder.getValues().get(ix);
|
||||||
|
assertEquals(COMPRESSABLE, response.getPayload().getType());
|
||||||
|
int length = response.getPayload().getBody().size();
|
||||||
|
assertEquals("comparison failed at index " + ix, responseSizes.get(ix).intValue(), length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void streamingInputCallShouldSucceed() throws Exception {
|
||||||
|
// Build the request.
|
||||||
|
String message = "hello world!";
|
||||||
|
StreamingInputCallRequest.Builder streamingInputBuilder =
|
||||||
|
StreamingInputCallRequest.newBuilder();
|
||||||
|
streamingInputBuilder.getPayloadBuilder().setType(PayloadType.COMPRESSABLE)
|
||||||
|
.setBody(ByteString.copyFromUtf8(message));
|
||||||
|
final StreamingInputCallRequest request = streamingInputBuilder.build();
|
||||||
|
|
||||||
|
StreamRecorder<StreamingInputCallResponse> recorder = StreamRecorder.create();
|
||||||
|
StreamObserver<StreamingInputCallRequest> requestStream =
|
||||||
|
asyncStub.streamingInputCall(recorder);
|
||||||
|
for (int ix = 10; ix > 0; --ix) {
|
||||||
|
// Send the request and close the request stream.
|
||||||
|
requestStream.onValue(request);
|
||||||
|
}
|
||||||
|
requestStream.onCompleted();
|
||||||
|
recorder.awaitCompletion();
|
||||||
|
assertSuccess(recorder);
|
||||||
|
assertEquals(1, recorder.getValues().size());
|
||||||
|
assertEquals(10 * message.length(), recorder.getValues().get(0).getAggregatedPayloadSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void fullDuplexCallShouldSucceed() throws Exception {
|
||||||
|
// Build the request.
|
||||||
|
List<Integer> responseSizes = Arrays.asList(50, 100, 150, 200);
|
||||||
|
StreamingOutputCallRequest.Builder streamingOutputBuilder =
|
||||||
|
StreamingOutputCallRequest.newBuilder();
|
||||||
|
streamingOutputBuilder.setResponseType(COMPRESSABLE);
|
||||||
|
for (Integer size : responseSizes) {
|
||||||
|
streamingOutputBuilder.addResponseParametersBuilder().setSize(size).setIntervalUs(0);
|
||||||
|
}
|
||||||
|
final StreamingOutputCallRequest request = streamingOutputBuilder.build();
|
||||||
|
|
||||||
|
StreamRecorder<StreamingOutputCallResponse> recorder = StreamRecorder.create();
|
||||||
|
StreamObserver<StreamingOutputCallRequest> requestStream =
|
||||||
|
blockingStub.fullDuplexCall(recorder);
|
||||||
|
|
||||||
|
final int numRequests = 10;
|
||||||
|
for (int ix = numRequests; ix > 0; --ix) {
|
||||||
|
requestStream.onValue(request);
|
||||||
|
}
|
||||||
|
requestStream.onCompleted();
|
||||||
|
recorder.awaitCompletion();
|
||||||
|
assertSuccess(recorder);
|
||||||
|
assertEquals(responseSizes.size() * numRequests, recorder.getValues().size());
|
||||||
|
for (int ix = 0; ix < recorder.getValues().size(); ++ix) {
|
||||||
|
StreamingOutputCallResponse response = recorder.getValues().get(ix);
|
||||||
|
assertEquals(COMPRESSABLE, response.getPayload().getType());
|
||||||
|
int length = response.getPayload().getBody().size();
|
||||||
|
int expectedSize = responseSizes.get(ix % responseSizes.size());
|
||||||
|
assertEquals("comparison failed at index " + ix, expectedSize, length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void halfDuplexCallShouldSucceed() throws Exception {
|
||||||
|
// Build the request.
|
||||||
|
List<Integer> responseSizes = Arrays.asList(50, 100, 150, 200);
|
||||||
|
StreamingOutputCallRequest.Builder streamingOutputBuilder =
|
||||||
|
StreamingOutputCallRequest.newBuilder();
|
||||||
|
streamingOutputBuilder.setResponseType(COMPRESSABLE);
|
||||||
|
for (Integer size : responseSizes) {
|
||||||
|
streamingOutputBuilder.addResponseParametersBuilder().setSize(size).setIntervalUs(0);
|
||||||
|
}
|
||||||
|
final StreamingOutputCallRequest request = streamingOutputBuilder.build();
|
||||||
|
|
||||||
|
StreamRecorder<StreamingOutputCallResponse> recorder = StreamRecorder.create();
|
||||||
|
StreamObserver<StreamingOutputCallRequest> requestStream = asyncStub.halfDuplexCall(recorder);
|
||||||
|
|
||||||
|
final int numRequests = 10;
|
||||||
|
for (int ix = numRequests; ix > 0; --ix) {
|
||||||
|
requestStream.onValue(request);
|
||||||
|
}
|
||||||
|
requestStream.onCompleted();
|
||||||
|
recorder.awaitCompletion();
|
||||||
|
assertSuccess(recorder);
|
||||||
|
assertEquals(responseSizes.size() * numRequests, recorder.getValues().size());
|
||||||
|
for (int ix = 0; ix < recorder.getValues().size(); ++ix) {
|
||||||
|
StreamingOutputCallResponse response = recorder.getValues().get(ix);
|
||||||
|
assertEquals(COMPRESSABLE, response.getPayload().getType());
|
||||||
|
int length = response.getPayload().getBody().size();
|
||||||
|
int expectedSize = responseSizes.get(ix % responseSizes.size());
|
||||||
|
assertEquals("comparison failed at index " + ix, expectedSize, length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void streamingOutputShouldBeFlowControlled() throws Exception {
|
||||||
|
// Create the call object.
|
||||||
|
Call<StreamingOutputCallRequest, StreamingOutputCallResponse> call =
|
||||||
|
channel.newCall(TestServiceGrpc.CONFIG.streamingOutputCall);
|
||||||
|
|
||||||
|
// Build the request.
|
||||||
|
List<Integer> responseSizes = Arrays.asList(50, 100, 150, 200);
|
||||||
|
StreamingOutputCallRequest.Builder streamingOutputBuilder =
|
||||||
|
StreamingOutputCallRequest.newBuilder();
|
||||||
|
streamingOutputBuilder.setResponseType(COMPRESSABLE);
|
||||||
|
for (Integer size : responseSizes) {
|
||||||
|
streamingOutputBuilder.addResponseParametersBuilder().setSize(size).setIntervalUs(0);
|
||||||
|
}
|
||||||
|
StreamingOutputCallRequest request = streamingOutputBuilder.build();
|
||||||
|
|
||||||
|
// Start the call and prepare capture of results.
|
||||||
|
final List<StreamingOutputCallResponse> results =
|
||||||
|
Collections.synchronizedList(new ArrayList<StreamingOutputCallResponse>());
|
||||||
|
final List<SettableFuture<Void>> processedFutures =
|
||||||
|
Collections.synchronizedList(new LinkedList<SettableFuture<Void>>());
|
||||||
|
final SettableFuture<Void> completionFuture = SettableFuture.create();
|
||||||
|
call.start(new Call.Listener<StreamingOutputCallResponse>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ListenableFuture<Void> onHeaders(Metadata.Headers headers) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ListenableFuture<Void> onPayload(final StreamingOutputCallResponse payload) {
|
||||||
|
SettableFuture<Void> processedFuture = SettableFuture.create();
|
||||||
|
results.add(payload);
|
||||||
|
processedFutures.add(processedFuture);
|
||||||
|
return processedFuture;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onClose(Status status, Metadata.Trailers trailers) {
|
||||||
|
if (status.isOk()) {
|
||||||
|
completionFuture.set(null);
|
||||||
|
} else {
|
||||||
|
completionFuture.setException(status.asException());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, new Metadata.Headers());
|
||||||
|
|
||||||
|
// Send the request.
|
||||||
|
call.sendPayload(request);
|
||||||
|
call.halfClose();
|
||||||
|
|
||||||
|
// Slowly set completion on all of the futures.
|
||||||
|
int expectedResults = responseSizes.size();
|
||||||
|
int count = 0;
|
||||||
|
while (count < expectedResults) {
|
||||||
|
if (!processedFutures.isEmpty()) {
|
||||||
|
assertEquals(1, processedFutures.size());
|
||||||
|
assertEquals(count + 1, results.size());
|
||||||
|
count++;
|
||||||
|
|
||||||
|
// Remove and set the first future to allow receipt of additional messages
|
||||||
|
// from flow control.
|
||||||
|
processedFutures.remove(0).set(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sleep a bit.
|
||||||
|
Uninterruptibles.sleepUninterruptibly(1, TimeUnit.SECONDS);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait for successful completion of the response.
|
||||||
|
completionFuture.get();
|
||||||
|
|
||||||
|
assertEquals(responseSizes.size(), results.size());
|
||||||
|
for (int ix = 0; ix < results.size(); ++ix) {
|
||||||
|
StreamingOutputCallResponse response = results.get(ix);
|
||||||
|
assertEquals(COMPRESSABLE, response.getPayload().getType());
|
||||||
|
int length = response.getPayload().getBody().size();
|
||||||
|
assertEquals("comparison failed at index " + ix, responseSizes.get(ix).intValue(), length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@org.junit.Test
|
||||||
|
public void exchangeContextUnaryCall() throws Exception {
|
||||||
|
Assume.assumeTrue(AbstractStream.GRPC_V2_PROTOCOL);
|
||||||
|
TestServiceGrpc.TestServiceBlockingStub stub =
|
||||||
|
TestServiceGrpc.newBlockingStub(channel);
|
||||||
|
|
||||||
|
// Capture the context exchange
|
||||||
|
Metadata.Headers fixedHeaders = new Metadata.Headers();
|
||||||
|
// Send a context proto (as it's in the default extension registry)
|
||||||
|
Messages.SimpleContext contextValue =
|
||||||
|
Messages.SimpleContext.newBuilder().setValue("dog").build();
|
||||||
|
fixedHeaders.put(METADATA_KEY, contextValue);
|
||||||
|
stub = MetadataUtils.attachHeaders(stub, fixedHeaders);
|
||||||
|
// .. and expect it to be echoed back in trailers
|
||||||
|
AtomicReference<Metadata.Trailers> trailersCapture = new AtomicReference<>();
|
||||||
|
AtomicReference<Metadata.Headers> headersCapture = new AtomicReference<>();
|
||||||
|
stub = MetadataUtils.captureMetadata(stub, headersCapture, trailersCapture);
|
||||||
|
|
||||||
|
Assert.assertNotNull(stub.unaryCall(unaryRequest()));
|
||||||
|
|
||||||
|
// Assert that our side channel object is echoed back in both headers and trailers
|
||||||
|
Assert.assertEquals(contextValue, headersCapture.get().get(METADATA_KEY));
|
||||||
|
if (AbstractStream.GRPC_V2_PROTOCOL) {
|
||||||
|
Assert.assertEquals(contextValue, trailersCapture.get().get(METADATA_KEY));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@org.junit.Test
|
||||||
|
public void exchangeContextStreamingCall() throws Exception {
|
||||||
|
Assume.assumeTrue(AbstractStream.GRPC_V2_PROTOCOL);
|
||||||
|
TestServiceGrpc.TestServiceBlockingStub stub =
|
||||||
|
TestServiceGrpc.newBlockingStub(channel);
|
||||||
|
|
||||||
|
// Capture the context exchange
|
||||||
|
Metadata.Headers fixedHeaders = new Metadata.Headers();
|
||||||
|
// Send a context proto (as it's in the default extension registry)
|
||||||
|
Messages.SimpleContext contextValue =
|
||||||
|
Messages.SimpleContext.newBuilder().setValue("dog").build();
|
||||||
|
fixedHeaders.put(METADATA_KEY, contextValue);
|
||||||
|
stub = MetadataUtils.attachHeaders(stub, fixedHeaders);
|
||||||
|
// .. and expect it to be echoed back in trailers
|
||||||
|
AtomicReference<Metadata.Trailers> trailersCapture = new AtomicReference<>();
|
||||||
|
AtomicReference<Metadata.Headers> headersCapture = new AtomicReference<>();
|
||||||
|
stub = MetadataUtils.captureMetadata(stub, headersCapture, trailersCapture);
|
||||||
|
|
||||||
|
List<Integer> responseSizes = Arrays.asList(50, 100, 150, 200);
|
||||||
|
Messages.StreamingOutputCallRequest.Builder streamingOutputBuilder =
|
||||||
|
Messages.StreamingOutputCallRequest.newBuilder();
|
||||||
|
streamingOutputBuilder.setResponseType(COMPRESSABLE);
|
||||||
|
for (Integer size : responseSizes) {
|
||||||
|
streamingOutputBuilder.addResponseParametersBuilder().setSize(size).setIntervalUs(0);
|
||||||
|
}
|
||||||
|
final Messages.StreamingOutputCallRequest request = streamingOutputBuilder.build();
|
||||||
|
|
||||||
|
StreamRecorder<Messages.StreamingOutputCallResponse> recorder = StreamRecorder.create();
|
||||||
|
StreamObserver<Messages.StreamingOutputCallRequest> requestStream =
|
||||||
|
stub.fullDuplexCall(recorder);
|
||||||
|
|
||||||
|
final int numRequests = 10;
|
||||||
|
for (int ix = numRequests; ix > 0; --ix) {
|
||||||
|
requestStream.onValue(request);
|
||||||
|
}
|
||||||
|
requestStream.onCompleted();
|
||||||
|
recorder.awaitCompletion();
|
||||||
|
assertSuccess(recorder);
|
||||||
|
org.junit.Assert.assertEquals(responseSizes.size() * numRequests, recorder.getValues().size());
|
||||||
|
|
||||||
|
// Assert that our side channel object is echoed back in both headers and trailers
|
||||||
|
Assert.assertEquals(contextValue, headersCapture.get().get(METADATA_KEY));
|
||||||
|
if (AbstractStream.GRPC_V2_PROTOCOL) {
|
||||||
|
Assert.assertEquals(contextValue, trailersCapture.get().get(METADATA_KEY));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected int unaryPayloadLength() {
|
||||||
|
// 10MiB.
|
||||||
|
return 10485760;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected SimpleRequest unaryRequest() {
|
||||||
|
SimpleRequest.Builder unaryBuilder = SimpleRequest.newBuilder();
|
||||||
|
unaryBuilder.getPayloadBuilder().setType(PayloadType.COMPRESSABLE);
|
||||||
|
byte[] data = new byte[unaryPayloadLength()];
|
||||||
|
new Random().nextBytes(data);
|
||||||
|
unaryBuilder.getPayloadBuilder().setBody(ByteString.copyFrom(data));
|
||||||
|
unaryBuilder.setResponseSize(10).setResponseType(PayloadType.COMPRESSABLE);
|
||||||
|
return unaryBuilder.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static void assertSuccess(StreamRecorder<?> recorder) {
|
||||||
|
if (recorder.getError() != null) {
|
||||||
|
throw new AssertionError("Error in stream", recorder.getError());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,78 @@
|
||||||
|
package com.google.net.stubby.transport.okhttp;
|
||||||
|
|
||||||
|
import com.google.common.base.Preconditions;
|
||||||
|
import com.google.common.util.concurrent.Service;
|
||||||
|
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||||
|
import com.google.net.stubby.AbstractChannelBuilder;
|
||||||
|
import com.google.net.stubby.SharedResourceHolder;
|
||||||
|
import com.google.net.stubby.SharedResourceHolder.Resource;
|
||||||
|
import com.google.net.stubby.transport.ClientTransportFactory;
|
||||||
|
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
|
||||||
|
/** Convenience class for building channels with the OkHttp transport. */
|
||||||
|
public final class OkHttpChannelBuilder extends AbstractChannelBuilder<OkHttpChannelBuilder> {
|
||||||
|
private static final Resource<ExecutorService> DEFAULT_TRANSPORT_THREAD_POOL
|
||||||
|
= new Resource<ExecutorService>() {
|
||||||
|
@Override
|
||||||
|
public ExecutorService create() {
|
||||||
|
return Executors.newCachedThreadPool(new ThreadFactoryBuilder()
|
||||||
|
.setNameFormat("grpc-okhttp-%d")
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close(ExecutorService executor) {
|
||||||
|
executor.shutdown();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Creates a new builder for the given server address. */
|
||||||
|
public static OkHttpChannelBuilder forAddress(InetSocketAddress serverAddress) {
|
||||||
|
return new OkHttpChannelBuilder(serverAddress);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Creates a new builder for the given server host and port. */
|
||||||
|
public static OkHttpChannelBuilder forAddress(String host, int port) {
|
||||||
|
return forAddress(new InetSocketAddress(host, port));
|
||||||
|
}
|
||||||
|
|
||||||
|
private final InetSocketAddress serverAddress;
|
||||||
|
private ExecutorService transportExecutor;
|
||||||
|
|
||||||
|
private OkHttpChannelBuilder(InetSocketAddress serverAddress) {
|
||||||
|
this.serverAddress = Preconditions.checkNotNull(serverAddress, "serverAddress");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Override the default executor necessary for internal transport use.
|
||||||
|
*
|
||||||
|
* <p>The channel does not take ownership of the given executor. It is the caller' responsibility
|
||||||
|
* to shutdown the executor when appropriate.
|
||||||
|
*/
|
||||||
|
public OkHttpChannelBuilder transportExecutor(ExecutorService executor) {
|
||||||
|
this.transportExecutor = executor;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ChannelEssentials buildEssentials() {
|
||||||
|
final ExecutorService executor = (transportExecutor == null)
|
||||||
|
? SharedResourceHolder.get(DEFAULT_TRANSPORT_THREAD_POOL) : transportExecutor;
|
||||||
|
ClientTransportFactory transportFactory
|
||||||
|
= new OkHttpClientTransportFactory(serverAddress, executor);
|
||||||
|
Service.Listener listener = null;
|
||||||
|
// We shut down the executor only if we created it.
|
||||||
|
if (transportExecutor == null) {
|
||||||
|
listener = new ClosureHook() {
|
||||||
|
@Override
|
||||||
|
protected void onClosed() {
|
||||||
|
SharedResourceHolder.release(DEFAULT_TRANSPORT_THREAD_POOL, executor);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return new ChannelEssentials(transportFactory, listener);
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue