Skip to content
This repository has been archived by the owner on Sep 26, 2023. It is now read-only.

Make ServiceApiSettings provider interfaces public #75

Merged
merged 9 commits into from
Apr 28, 2016
30 changes: 18 additions & 12 deletions src/main/java/com/google/api/gax/core/ConnectionSettings.java
Original file line number Diff line number Diff line change
Expand Up @@ -56,25 +56,31 @@
@AutoValue
public abstract class ConnectionSettings {

/*
* package-private so that the AutoValue derived class can access it
/**
* Provides an interface to hold and acquire the credentials that will be used to call the
* service.
*/
interface CredentialsProvider {
public interface CredentialsProvider {

This comment was marked as spam.

/**
* Gets the credentials which will be used to call the service. If the credentials have not been
* acquired yet, then they will be acquired when this function is called.
*/
Credentials getCredentials() throws IOException;
}

/**
* Gets the credentials which will be used to call the service. If the credentials
* have not been acquired yet, then they will be acquired when this function is called.
* Gets the credentials which will be used to call the service. If the credentials have not been
* acquired yet, then they will be acquired when this function is called.
*/
public Credentials getCredentials() throws IOException {
public Credentials getOrBuildCredentials() throws IOException {

This comment was marked as spam.

return getCredentialsProvider().getCredentials();
}

/*
* package-private so that the AutoValue derived class can access it
/**
* The credentials to use in order to call the service. Credentials will not be acquired until
* they are required.
*/
abstract CredentialsProvider getCredentialsProvider();
public abstract CredentialsProvider getCredentialsProvider();

/**
* The address used to reach the service.
Expand All @@ -97,10 +103,10 @@ public Builder toBuilder() {
@AutoValue.Builder
public abstract static class Builder {

/*
* package-private so that the AutoValue derived class can access it
/**
* Set the credentials to use in order to call the service.
*/
abstract Builder setCredentialsProvider(CredentialsProvider provider);
public abstract Builder setCredentialsProvider(CredentialsProvider provider);

/**
* Sets the credentials to use in order to call the service.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ protected ApiCallable<RequestT, ResponseT> createBaseCallable(
new DescriptorClientCallFactory<>(methodDescriptor);
ApiCallable<RequestT, ResponseT> callable =
new ApiCallable<>(new DirectCallable<>(clientCallFactory), this);
ManagedChannel channel = serviceSettings.getChannel();
ScheduledExecutorService executor = serviceSettings.getExecutor();
ManagedChannel channel = serviceSettings.getOrBuildChannel();
ScheduledExecutorService executor = serviceSettings.getOrBuildExecutor();
if (getRetryableCodes() != null) {
callable = callable.retryableOn(ImmutableSet.copyOf(getRetryableCodes()));
}
Expand Down
178 changes: 104 additions & 74 deletions src/main/java/com/google/api/gax/grpc/ServiceApiSettings.java
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,44 @@
*/
public abstract class ServiceApiSettings {

private final ManagedChannel channel;
private final boolean shouldAutoCloseChannel;
private final ScheduledExecutorService executor;
/**
* Provides an interface to hold and build the channel that will be used. If the channel does not
* already exist, it will not be constructed until getChannel is called.
*/
public interface ChannelProvider {
/**
* Connection settings used to build the channel. If a channel is provided directly this will be
* set to null.
*/
@Nullable
ConnectionSettings connectionSettings();

/**
* Indicates whether the channel should be closed by the containing API class.
*/
boolean shouldAutoClose();

/**
* Get the channel to be used to connect to the service. The first time this is called, if the
* channel does not already exist, it will be created.
*/
ManagedChannel getChannel(Executor executor) throws IOException;
}

@Nullable
private final ConnectionSettings connectionSettings;
/**
* Provides an interface to hold and create the Executor to be used. If the executor does not
* already exist, it will not be constructed until getExecutor is called.
*/
public interface ExecutorProvider {
/**
* Get the executor to be used to connect to the service. The first time this is called, if the
* executor does not already exist, it will be created.
*/
ScheduledExecutorService getExecutor();
}

private final ChannelProvider channelProvider;
private final ExecutorProvider executorProvider;

private final String generatorName;
private final String generatorVersion;
Expand All @@ -66,34 +98,51 @@ public abstract class ServiceApiSettings {
/**
* Constructs an instance of ServiceApiSettings.
*/
protected ServiceApiSettings(ManagedChannel channel,
boolean shouldAutoCloseChannel,
ScheduledExecutorService executor,
ConnectionSettings connectionSettings,
String generatorName,
String generatorVersion,
String clientLibName,
String clientLibVersion) {
this.channel = channel;
this.executor = executor;
this.connectionSettings = connectionSettings;
this.shouldAutoCloseChannel = shouldAutoCloseChannel;
protected ServiceApiSettings(
ChannelProvider channelProvider,
ExecutorProvider executorProvider,
String generatorName,
String generatorVersion,
String clientLibName,
String clientLibVersion) {
this.channelProvider = channelProvider;
this.executorProvider = executorProvider;
this.clientLibName = clientLibName;
this.clientLibVersion = clientLibVersion;
this.generatorName = generatorName;
this.generatorVersion = generatorVersion;
}

public final ManagedChannel getChannel() {
return channel;
/**
* Return the channel to be used to connect to the service, retrieved using the channelProvider.
* If no channel was set, a default channel will be instantiated.
*/
public final ManagedChannel getOrBuildChannel() throws IOException {
return getChannelProvider().getChannel(getOrBuildExecutor());

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.

}

public final ScheduledExecutorService getExecutor() {
return executor;
/**
* Return the channel provider. If no channel provider was set, the default channel provider will
* be returned.
*/
public final ChannelProvider getChannelProvider() {
return channelProvider;
}

public final boolean shouldAutoCloseChannel() {
return shouldAutoCloseChannel;
/**
* The Executor used for channels, retries, and bundling, retrieved using the executorProvider. If
* no executor was set, a default executor will be instantiated.
*/
public final ScheduledExecutorService getOrBuildExecutor() {
return getExecutorProvider().getExecutor();
}

/**
* Return the executor provider. It no executor provider was set, the default executor provider
* will be returned.
*/
public final ExecutorProvider getExecutorProvider() {
return executorProvider;
}

public abstract static class Builder {
Expand All @@ -114,16 +163,6 @@ public abstract static class Builder {
private ChannelProvider channelProvider;
private ExecutorProvider executorProvider;

private interface ChannelProvider {
ConnectionSettings connectionSettings();
boolean shouldAutoClose();
ManagedChannel getChannel(Executor executor) throws IOException;
}

private interface ExecutorProvider {
ScheduledExecutorService getExecutor();
}

protected Builder(ConnectionSettings connectionSettings) {
this();
channelProvider = createChannelProvider(connectionSettings);
Expand All @@ -134,11 +173,7 @@ protected Builder(ConnectionSettings connectionSettings) {
*/
protected Builder(ServiceApiSettings settings) {
this();
if (settings.connectionSettings != null) {
channelProvider = createChannelProvider(settings.connectionSettings);
} else {
channelProvider = createChannelProvider(settings.channel, settings.shouldAutoCloseChannel);
}
this.channelProvider = settings.channelProvider;

This comment was marked as spam.

this.clientLibName = settings.clientLibName;
this.clientLibVersion = settings.clientLibVersion;
this.serviceGeneratorName = settings.generatorName;
Expand All @@ -165,13 +200,20 @@ public ScheduledExecutorService getExecutor() {
};
}

/**
* Set the executor provider to be used.
*/
public Builder setExecutorProvider(ExecutorProvider executorProvider) {
this.executorProvider = executorProvider;
return this;
}

/**
* Sets the executor to use for channels, retries, and bundling.
*
* It is up to the user to terminate the {@code Executor} when it is no longer needed.
*/
public Builder setExecutor(final ScheduledExecutorService executor) {
public Builder provideExecutorWith(final ScheduledExecutorService executor) {
executorProvider = new ExecutorProvider() {
@Override
public ScheduledExecutorService getExecutor() {
Expand All @@ -182,44 +224,31 @@ public ScheduledExecutorService getExecutor() {
}

/**
* Sets a channel for this ServiceApiSettings to use. This prevents a channel
* from being created.
*
* See class documentation for more details on channels.
*/
public Builder provideChannelWith(
final ManagedChannel channel, final boolean shouldAutoClose) {
channelProvider = createChannelProvider(channel, shouldAutoClose);
return this;
}

/**
* Provides the connection settings necessary to create a channel.
* Set the channel provider to be used.
*/
public Builder provideChannelWith(
final ConnectionSettings settings) {
channelProvider = createChannelProvider(settings);
public Builder setChannelProvider(ChannelProvider channelProvider) {
this.channelProvider = channelProvider;
return this;
}

/**
* The channel used to send requests to the service.
*
* If no channel was set, a default channel will be instantiated, using
* the connection settings provided.
* Sets a channel for this ServiceApiSettings to use. This prevents a channel from being
* created.
*
* See class documentation for more details on channels.
*/
public ManagedChannel getOrBuildChannel() throws IOException {
return channelProvider.getChannel(this.getOrBuildExecutor());
public Builder provideChannelWith(final ManagedChannel channel, final boolean shouldAutoClose) {
setChannelProvider(createChannelProvider(channel, shouldAutoClose));
return this;
}

/**
* The Executor used for channels, retries, and bundling..
* If no executor was set, a default executor will be instantiated.
* Provides the connection settings necessary to create a channel.
*/
public ScheduledExecutorService getOrBuildExecutor() {
return executorProvider.getExecutor();
public Builder provideChannelWith(
final ConnectionSettings settings) {
setChannelProvider(createChannelProvider(settings));
return this;
}

/**
Expand All @@ -240,6 +269,14 @@ public Builder setClientLibHeader(String name, String version) {
return this;
}

public ChannelProvider getChannelProvider() {
return channelProvider;
}

public ExecutorProvider getExecutorProvider() {
return executorProvider;
}

public String getClientLibName() {
return clientLibName;
}
Expand All @@ -256,14 +293,6 @@ public String getGeneratorVersion() {
return serviceGeneratorVersion;
}

public ConnectionSettings getConnectionSettings() {
return channelProvider.connectionSettings();
}

public boolean shouldAutoCloseChannel() {
return channelProvider.shouldAutoClose();
}

/**
* Performs a merge, using only non-null fields
*/
Expand All @@ -289,14 +318,15 @@ protected Builder applyToAllApiMethods(
private ChannelProvider createChannelProvider(final ConnectionSettings settings) {
return new ChannelProvider() {
private ManagedChannel channel = null;

@Override
public ManagedChannel getChannel(Executor executor) throws IOException {
if (channel != null) {
return channel;
}

List<ClientInterceptor> interceptors = Lists.newArrayList();
interceptors.add(new ClientAuthInterceptor(settings.getCredentials(), executor));
interceptors.add(new ClientAuthInterceptor(settings.getOrBuildCredentials(), executor));
interceptors.add(new HeaderInterceptor(serviceHeader()));

channel = NettyChannelBuilder.forAddress(settings.getServiceAddress(), settings.getPort())
Expand Down