Skip to content

Commit e51c55d

Browse files
authored
feat: support setting core pool size for async API in system property (#2632)
Add support for setting the core pool size for the thread pool that is used for the Async API using a system property. This allows users to change this property without having to change code, and to set the property if they are using a framework that builds on top of the client library, but that does not have a configuration option for setting a custom executor provider. Fixes #2631
1 parent 7be4df1 commit e51c55d

File tree

2 files changed

+81
-1
lines changed

2 files changed

+81
-1
lines changed

google-cloud-spanner/src/main/java/com/google/cloud/spanner/SpannerOptions.java

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -524,7 +524,30 @@ public static FixedCloseableExecutorProvider create(ScheduledExecutorService exe
524524
*/
525525
@VisibleForTesting
526526
static CloseableExecutorProvider createDefaultAsyncExecutorProvider() {
527-
return createAsyncExecutorProvider(8, 60L, TimeUnit.SECONDS);
527+
return createAsyncExecutorProvider(
528+
getDefaultAsyncExecutorProviderCoreThreadCount(), 60L, TimeUnit.SECONDS);
529+
}
530+
531+
@VisibleForTesting
532+
static int getDefaultAsyncExecutorProviderCoreThreadCount() {
533+
String propertyName = "SPANNER_ASYNC_NUM_CORE_THREADS";
534+
String propertyValue = System.getProperty(propertyName, "8");
535+
try {
536+
int corePoolSize = Integer.parseInt(propertyValue);
537+
if (corePoolSize < 0) {
538+
throw SpannerExceptionFactory.newSpannerException(
539+
ErrorCode.INVALID_ARGUMENT,
540+
String.format(
541+
"The value for %s must be >=0. Invalid value: %s", propertyName, propertyValue));
542+
}
543+
return corePoolSize;
544+
} catch (NumberFormatException exception) {
545+
throw SpannerExceptionFactory.newSpannerException(
546+
ErrorCode.INVALID_ARGUMENT,
547+
String.format(
548+
"The %s system property must be a valid integer. The value %s could not be parsed as an integer.",
549+
propertyName, propertyValue));
550+
}
528551
}
529552

530553
/**

google-cloud-spanner/src/test/java/com/google/cloud/spanner/SpannerOptionsTest.java

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@
6363
import java.util.HashMap;
6464
import java.util.List;
6565
import java.util.Map;
66+
import java.util.concurrent.Callable;
6667
import java.util.concurrent.ScheduledExecutorService;
6768
import javax.annotation.Nonnull;
6869
import org.junit.Test;
@@ -913,6 +914,62 @@ public void testCustomAsyncExecutorProvider() {
913914
assertSame(service, options.getAsyncExecutorProvider().getExecutor());
914915
}
915916

917+
@Test
918+
public void testAsyncExecutorProviderCoreThreadCount() throws Exception {
919+
assertEquals(8, SpannerOptions.getDefaultAsyncExecutorProviderCoreThreadCount());
920+
String propertyName = "SPANNER_ASYNC_NUM_CORE_THREADS";
921+
assertEquals(
922+
Integer.valueOf(8),
923+
runWithSystemProperty(
924+
propertyName, null, SpannerOptions::getDefaultAsyncExecutorProviderCoreThreadCount));
925+
assertEquals(
926+
Integer.valueOf(16),
927+
runWithSystemProperty(
928+
propertyName, "16", SpannerOptions::getDefaultAsyncExecutorProviderCoreThreadCount));
929+
assertEquals(
930+
Integer.valueOf(1),
931+
runWithSystemProperty(
932+
propertyName, "1", SpannerOptions::getDefaultAsyncExecutorProviderCoreThreadCount));
933+
assertThrows(
934+
SpannerException.class,
935+
() ->
936+
runWithSystemProperty(
937+
propertyName,
938+
"foo",
939+
SpannerOptions::getDefaultAsyncExecutorProviderCoreThreadCount));
940+
assertThrows(
941+
SpannerException.class,
942+
() ->
943+
runWithSystemProperty(
944+
propertyName,
945+
"-1",
946+
SpannerOptions::getDefaultAsyncExecutorProviderCoreThreadCount));
947+
assertThrows(
948+
SpannerException.class,
949+
() ->
950+
runWithSystemProperty(
951+
propertyName, "", SpannerOptions::getDefaultAsyncExecutorProviderCoreThreadCount));
952+
}
953+
954+
static <V> V runWithSystemProperty(
955+
String propertyName, String propertyValue, Callable<V> callable) throws Exception {
956+
String currentValue = System.getProperty(propertyName);
957+
if (propertyValue == null) {
958+
System.clearProperty(propertyName);
959+
} else {
960+
System.setProperty(propertyName, propertyValue);
961+
}
962+
try {
963+
return callable.call();
964+
} finally {
965+
if (currentValue == null) {
966+
System.clearProperty(propertyName);
967+
} else {
968+
System.setProperty(propertyName, currentValue);
969+
}
970+
}
971+
}
972+
916973
@Test
917974
public void testDefaultNumChannelsWithGrpcGcpExtensionEnabled() {
918975
SpannerOptions options =

0 commit comments

Comments
 (0)