Skip to content

Commit ca55b6f

Browse files
authored
cronet: allow application to provide all threads
1 parent 7c69c3a commit ca55b6f

File tree

2 files changed

+64
-3
lines changed

2 files changed

+64
-3
lines changed

cronet/src/main/java/io/grpc/cronet/CronetChannelBuilder.java

+31-3
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package io.grpc.cronet;
1818

1919
import static com.google.common.base.Preconditions.checkArgument;
20+
import static com.google.common.base.Preconditions.checkNotNull;
2021
import static io.grpc.internal.GrpcUtil.DEFAULT_MAX_MESSAGE_SIZE;
2122

2223
import com.google.common.annotations.VisibleForTesting;
@@ -73,6 +74,9 @@ public static CronetChannelBuilder forAddress(String name, int port) {
7374
throw new UnsupportedOperationException("call forAddress(String, int, CronetEngine) instead");
7475
}
7576

77+
@Nullable
78+
private ScheduledExecutorService scheduledExecutorService;
79+
7680
private final CronetEngine cronetEngine;
7781

7882
private boolean alwaysUsePut = false;
@@ -161,12 +165,30 @@ public final CronetChannelBuilder setTrafficStatsUid(int uid) {
161165
return this;
162166
}
163167

168+
/**
169+
* Provides a custom scheduled executor service.
170+
*
171+
* <p>It's an optional parameter. If the user has not provided a scheduled executor service when
172+
* the channel is built, the builder will use a static cached thread pool.
173+
*
174+
* @return this
175+
*
176+
* @since 1.12.0
177+
*/
178+
public final CronetChannelBuilder scheduledExecutorService(
179+
ScheduledExecutorService scheduledExecutorService) {
180+
this.scheduledExecutorService =
181+
checkNotNull(scheduledExecutorService, "scheduledExecutorService");
182+
return this;
183+
}
184+
164185
@Override
165186
protected final ClientTransportFactory buildTransportFactory() {
166187
return new CronetTransportFactory(
167188
new TaggingStreamFactory(
168189
cronetEngine, trafficStatsTagSet, trafficStatsTag, trafficStatsUidSet, trafficStatsUid),
169190
MoreExecutors.directExecutor(),
191+
scheduledExecutorService,
170192
maxMessageSize,
171193
alwaysUsePut,
172194
transportTracerFactory.create());
@@ -180,20 +202,24 @@ protected Attributes getNameResolverParams() {
180202

181203
@VisibleForTesting
182204
static class CronetTransportFactory implements ClientTransportFactory {
183-
private final ScheduledExecutorService timeoutService =
184-
SharedResourceHolder.get(GrpcUtil.TIMER_SERVICE);
205+
private final ScheduledExecutorService timeoutService;
185206
private final Executor executor;
186207
private final int maxMessageSize;
187208
private final boolean alwaysUsePut;
188209
private final StreamBuilderFactory streamFactory;
189210
private final TransportTracer transportTracer;
211+
private final boolean usingSharedScheduler;
190212

191213
private CronetTransportFactory(
192214
StreamBuilderFactory streamFactory,
193215
Executor executor,
216+
@Nullable ScheduledExecutorService timeoutService,
194217
int maxMessageSize,
195218
boolean alwaysUsePut,
196219
TransportTracer transportTracer) {
220+
usingSharedScheduler = timeoutService == null;
221+
this.timeoutService = usingSharedScheduler
222+
? SharedResourceHolder.get(GrpcUtil.TIMER_SERVICE) : timeoutService;
197223
this.maxMessageSize = maxMessageSize;
198224
this.alwaysUsePut = alwaysUsePut;
199225
this.streamFactory = streamFactory;
@@ -216,7 +242,9 @@ public ScheduledExecutorService getScheduledExecutorService() {
216242

217243
@Override
218244
public void close() {
219-
SharedResourceHolder.release(GrpcUtil.TIMER_SERVICE, timeoutService);
245+
if (usingSharedScheduler) {
246+
SharedResourceHolder.release(GrpcUtil.TIMER_SERVICE, timeoutService);
247+
}
220248
}
221249
}
222250

cronet/src/test/java/io/grpc/cronet/CronetChannelBuilderTest.java

+33
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,21 @@
1616

1717
package io.grpc.cronet;
1818

19+
import static io.grpc.internal.GrpcUtil.TIMER_SERVICE;
1920
import static org.junit.Assert.assertFalse;
21+
import static org.junit.Assert.assertSame;
2022
import static org.junit.Assert.assertTrue;
23+
import static org.mockito.Mockito.mock;
2124

2225
import io.grpc.CallOptions;
2326
import io.grpc.Metadata;
2427
import io.grpc.MethodDescriptor;
2528
import io.grpc.cronet.CronetChannelBuilder.CronetTransportFactory;
29+
import io.grpc.internal.ClientTransportFactory;
30+
import io.grpc.internal.SharedResourceHolder;
2631
import io.grpc.testing.TestMethodDescriptors;
2732
import java.net.InetSocketAddress;
33+
import java.util.concurrent.ScheduledExecutorService;
2834
import org.chromium.net.ExperimentalCronetEngine;
2935
import org.junit.Before;
3036
import org.junit.Test;
@@ -73,4 +79,31 @@ public void alwaysUsePut_defaultsToFalse() throws Exception {
7379

7480
assertFalse(stream.idempotent);
7581
}
82+
83+
@Test
84+
public void scheduledExecutorService_default() {
85+
CronetChannelBuilder builder = CronetChannelBuilder.forAddress("address", 1234, mockEngine);
86+
ClientTransportFactory clientTransportFactory = builder.buildTransportFactory();
87+
assertSame(
88+
SharedResourceHolder.get(TIMER_SERVICE),
89+
clientTransportFactory.getScheduledExecutorService());
90+
91+
SharedResourceHolder.release(
92+
TIMER_SERVICE, clientTransportFactory.getScheduledExecutorService());
93+
clientTransportFactory.close();
94+
}
95+
96+
@Test
97+
public void scheduledExecutorService_custom() {
98+
CronetChannelBuilder builder = CronetChannelBuilder.forAddress("address", 1234, mockEngine);
99+
ScheduledExecutorService scheduledExecutorService = mock(ScheduledExecutorService.class);
100+
101+
CronetChannelBuilder builder1 = builder.scheduledExecutorService(scheduledExecutorService);
102+
assertSame(builder, builder1);
103+
104+
ClientTransportFactory clientTransportFactory = builder1.buildTransportFactory();
105+
assertSame(scheduledExecutorService, clientTransportFactory.getScheduledExecutorService());
106+
107+
clientTransportFactory.close();
108+
}
76109
}

0 commit comments

Comments
 (0)