Skip to content

Commit 6837e91

Browse files
committed
Add base service option classes for gRPC and HTTP services
1 parent 1eded7e commit 6837e91

File tree

16 files changed

+907
-205
lines changed

16 files changed

+907
-205
lines changed

gcloud-java-bigquery/src/main/java/com/google/cloud/bigquery/BigQueryOptions.java

+4-4
Original file line numberDiff line numberDiff line change
@@ -16,19 +16,19 @@
1616

1717
package com.google.cloud.bigquery;
1818

19+
import com.google.cloud.HttpServiceOptions;
1920
import com.google.common.collect.ImmutableSet;
20-
import com.google.cloud.ServiceOptions;
2121
import com.google.cloud.bigquery.spi.BigQueryRpc;
2222
import com.google.cloud.bigquery.spi.BigQueryRpcFactory;
2323
import com.google.cloud.bigquery.spi.DefaultBigQueryRpc;
2424

2525
import java.util.Set;
2626

27-
public class BigQueryOptions extends ServiceOptions<BigQuery, BigQueryRpc, BigQueryOptions> {
27+
public class BigQueryOptions extends HttpServiceOptions<BigQuery, BigQueryRpc, BigQueryOptions> {
2828

2929
private static final String BIGQUERY_SCOPE = "https://www.googleapis.com/auth/bigquery";
3030
private static final Set<String> SCOPES = ImmutableSet.of(BIGQUERY_SCOPE);
31-
private static final long serialVersionUID = -215981591481708043L;
31+
private static final long serialVersionUID = -8592198255032667206L;
3232

3333
public static class DefaultBigqueryFactory implements BigQueryFactory {
3434

@@ -51,7 +51,7 @@ public BigQueryRpc create(BigQueryOptions options) {
5151
}
5252

5353
public static class Builder extends
54-
ServiceOptions.Builder<BigQuery, BigQueryRpc, BigQueryOptions, Builder> {
54+
HttpServiceOptions.Builder<BigQuery, BigQueryRpc, BigQueryOptions, Builder> {
5555

5656
private Builder() {
5757
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,229 @@
1+
/*
2+
* Copyright 2016 Google Inc. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.google.cloud;
18+
19+
import com.google.cloud.spi.ServiceRpcFactory;
20+
import com.google.common.base.Preconditions;
21+
22+
import io.grpc.internal.SharedResourceHolder;
23+
import io.grpc.internal.SharedResourceHolder.Resource;
24+
25+
import java.util.Objects;
26+
import java.util.concurrent.ScheduledExecutorService;
27+
import java.util.concurrent.ScheduledThreadPoolExecutor;
28+
import java.util.concurrent.TimeUnit;
29+
30+
/**
31+
* Abstract class representing service options for those services that use gRPC as the transport
32+
* layer.
33+
*
34+
* @param <ServiceT> the service subclass
35+
* @param <ServiceRpcT> the spi-layer class corresponding to the service
36+
* @param <OptionsT> the {@code ServiceOptions} subclass corresponding to the service
37+
*/
38+
public abstract class GrpcServiceOptions<ServiceT extends Service<OptionsT>, ServiceRpcT,
39+
OptionsT extends GrpcServiceOptions<ServiceT, ServiceRpcT, OptionsT>>
40+
extends ServiceOptions<ServiceT, ServiceRpcT, OptionsT> {
41+
42+
private static final long serialVersionUID = 6415982522610509549L;
43+
private final int initialTimeout;
44+
private final double timeoutMultiplier;
45+
private final int maxTimeout;
46+
47+
/**
48+
* Shared thread pool executor.
49+
*/
50+
private static final Resource<ScheduledExecutorService> EXECUTOR =
51+
new Resource<ScheduledExecutorService>() {
52+
@Override
53+
public ScheduledExecutorService create() {
54+
ScheduledThreadPoolExecutor service = new ScheduledThreadPoolExecutor(8);
55+
service.setKeepAliveTime(5, TimeUnit.SECONDS);
56+
service.allowCoreThreadTimeOut(true);
57+
service.setRemoveOnCancelPolicy(true);
58+
return service;
59+
}
60+
61+
@Override
62+
public void close(ScheduledExecutorService instance) {
63+
instance.shutdown();
64+
}
65+
};
66+
67+
/**
68+
* An interface that provides access to a scheduled executor service.
69+
*/
70+
public interface ExecutorProvider {
71+
72+
/**
73+
* Returns the scheduled executor service.
74+
*/
75+
ScheduledExecutorService get();
76+
77+
/**
78+
* Shuts down the scheduled executor service if it is no longer used.
79+
*/
80+
void shutdown();
81+
}
82+
83+
/**
84+
* An interface that provides access to a scheduled executor service.
85+
*/
86+
private static class DefaultExecutorProvider implements ExecutorProvider {
87+
88+
private ScheduledExecutorService service;
89+
private boolean shutdown = false;
90+
91+
private DefaultExecutorProvider() {}
92+
93+
@Override
94+
public synchronized ScheduledExecutorService get() {
95+
if (service == null && !shutdown) {
96+
service = SharedResourceHolder.get(EXECUTOR);
97+
}
98+
return service;
99+
}
100+
101+
@Override
102+
public synchronized void shutdown() {
103+
if (service != null && !shutdown) {
104+
shutdown = true;
105+
service = SharedResourceHolder.release(EXECUTOR, service);
106+
}
107+
}
108+
}
109+
110+
/**
111+
* Builder for {@code GrpcServiceOptions}.
112+
*
113+
* @param <ServiceT> the service subclass
114+
* @param <ServiceRpcT> the spi-layer class corresponding to the service
115+
* @param <OptionsT> the {@code GrpcServiceOptions} subclass corresponding to the service
116+
* @param <B> the {@code ServiceOptions} builder
117+
*/
118+
protected abstract static class Builder<ServiceT extends Service<OptionsT>, ServiceRpcT,
119+
OptionsT extends GrpcServiceOptions<ServiceT, ServiceRpcT, OptionsT>,
120+
B extends Builder<ServiceT, ServiceRpcT, OptionsT, B>>
121+
extends ServiceOptions.Builder<ServiceT, ServiceRpcT, OptionsT, B> {
122+
123+
private int initialTimeout = 20_000;
124+
private double timeoutMultiplier = 1.5;
125+
private int maxTimeout = 100_000;
126+
127+
protected Builder() {}
128+
129+
protected Builder(GrpcServiceOptions<ServiceT, ServiceRpcT, OptionsT> options) {
130+
super(options);
131+
initialTimeout = options.initialTimeout;
132+
timeoutMultiplier = options.timeoutMultiplier;
133+
maxTimeout = options.maxTimeout;
134+
}
135+
136+
@Override
137+
protected abstract GrpcServiceOptions<ServiceT, ServiceRpcT, OptionsT> build();
138+
139+
/**
140+
* Sets the timeout for the initial RPC, in milliseconds. Subsequent calls will use this value
141+
* adjusted according to {@link #timeoutMultiplier(double)}. Default value is 20000.
142+
*
143+
* @throws IllegalArgumentException if the provided timeout is &lt; 0
144+
* @return the builder
145+
*/
146+
public B initialTimeout(int initialTimeout) {
147+
Preconditions.checkArgument(initialTimeout > 0, "Initial timeout must be > 0");
148+
this.initialTimeout = initialTimeout;
149+
return self();
150+
}
151+
152+
/**
153+
* Sets the timeout multiplier. This value is used to compute the timeout for a retried RPC.
154+
* Timeout is computed as {@code timeoutMultiplier * previousTimeout}. Default value is 1.5.
155+
*
156+
* @throws IllegalArgumentException if the provided timeout multiplier is &lt; 0
157+
* @return the builder
158+
*/
159+
public B timeoutMultiplier(double timeoutMultiplier) {
160+
Preconditions.checkArgument(timeoutMultiplier >= 1.0, "Timeout multiplier must be >= 1");
161+
this.timeoutMultiplier = timeoutMultiplier;
162+
return self();
163+
}
164+
165+
/**
166+
* Sets the maximum timeout for a RPC call, in milliseconds. Default value is 100000. If
167+
* {@code maxTimeout} is lower than the initial timeout the {@link #initialTimeout(int)} value
168+
* is used instead.
169+
*
170+
* @return the builder
171+
*/
172+
public B maxTimeout(int maxTimeout) {
173+
this.maxTimeout = maxTimeout;
174+
return self();
175+
}
176+
}
177+
178+
protected GrpcServiceOptions(
179+
Class<? extends ServiceFactory<ServiceT, OptionsT>> serviceFactoryClass,
180+
Class<? extends ServiceRpcFactory<ServiceRpcT, OptionsT>> rpcFactoryClass, Builder<ServiceT,
181+
ServiceRpcT, OptionsT, ?> builder) {
182+
super(serviceFactoryClass, rpcFactoryClass, builder);
183+
initialTimeout = builder.initialTimeout;
184+
timeoutMultiplier = builder.timeoutMultiplier;
185+
maxTimeout = builder.maxTimeout <= initialTimeout ? initialTimeout : builder.maxTimeout;
186+
}
187+
188+
/**
189+
* Returns a scheduled executor service provider.
190+
*/
191+
protected ExecutorProvider executorProvider() {
192+
return new DefaultExecutorProvider();
193+
}
194+
195+
/**
196+
* Returns the timeout for the initial RPC, in milliseconds. Subsequent calls will use this value
197+
* adjusted according to {@link #timeoutMultiplier()}. Default value is 20000.
198+
*/
199+
public int initialTimeout() {
200+
return initialTimeout;
201+
}
202+
203+
/**
204+
* Returns the timeout multiplier. This values is used to compute the timeout for a RPC. Timeout
205+
* is computed as {@code timeoutMultiplier * previousTimeout}. Default value is 1.5.
206+
*/
207+
public double timeoutMultiplier() {
208+
return timeoutMultiplier;
209+
}
210+
211+
/**
212+
* Returns the maximum timeout for a RPC call, in milliseconds. Default value is 100000.
213+
*/
214+
public int maxTimeout() {
215+
return maxTimeout;
216+
}
217+
218+
@Override
219+
protected int baseHashCode() {
220+
return Objects.hash(super.baseHashCode(), initialTimeout, timeoutMultiplier, maxTimeout);
221+
}
222+
223+
protected boolean baseEquals(GrpcServiceOptions<?, ?, ?> other) {
224+
return super.baseEquals(other)
225+
&& Objects.equals(initialTimeout, other.initialTimeout)
226+
&& Objects.equals(timeoutMultiplier, other.timeoutMultiplier)
227+
&& Objects.equals(maxTimeout, other.maxTimeout);
228+
}
229+
}

0 commit comments

Comments
 (0)