Skip to content

Commit bd3714f

Browse files
committed
chore(spanner): Auto-enable location API and dynamic channel pool for experimental hosts, and merge default dynamic
channel pool options with user-provided options When an experimental host is configured, automatically enable the location API (unless explicitly disabled via GOOGLE_SPANNER_EXPERIMENTAL_LOCATION_API=false) and dynamic channel pool (unless explicitly disabled via disableDynamicChannelPool()). Also fix an issue where setting custom GcpChannelPoolOptions without specifying dynamic scaling parameters (minRpcPerChannel, maxRpcPerChannel, scaleDownInterval) would reset them to zero, preventing channel scale-up. Custom options are now merged with Spanner defaults so unset fields retain their default values.
1 parent 4cb170d commit bd3714f

File tree

1 file changed

+66
-10
lines changed

1 file changed

+66
-10
lines changed

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

Lines changed: 66 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ public class SpannerOptions extends ServiceOptions<Spanner, SpannerOptions> {
141141

142142
// Dynamic Channel Pool (DCP) default values and bounds
143143
/** Default max concurrent RPCs per channel before triggering scale up. */
144-
public static final int DEFAULT_DYNAMIC_POOL_MAX_RPC = 25;
144+
public static final int DEFAULT_DYNAMIC_POOL_MAX_RPC = 90;
145145

146146
/** Default min concurrent RPCs per channel for scale down check. */
147147
public static final int DEFAULT_DYNAMIC_POOL_MIN_RPC = 15;
@@ -150,13 +150,13 @@ public class SpannerOptions extends ServiceOptions<Spanner, SpannerOptions> {
150150
public static final Duration DEFAULT_DYNAMIC_POOL_SCALE_DOWN_INTERVAL = Duration.ofMinutes(3);
151151

152152
/** Default initial number of channels for dynamic pool. */
153-
public static final int DEFAULT_DYNAMIC_POOL_INITIAL_SIZE = 4;
153+
public static final int DEFAULT_DYNAMIC_POOL_INITIAL_SIZE = 1;
154154

155155
/** Default max number of channels for dynamic pool. */
156-
public static final int DEFAULT_DYNAMIC_POOL_MAX_CHANNELS = 10;
156+
public static final int DEFAULT_DYNAMIC_POOL_MAX_CHANNELS = 256;
157157

158158
/** Default min number of channels for dynamic pool. */
159-
public static final int DEFAULT_DYNAMIC_POOL_MIN_CHANNELS = 2;
159+
public static final int DEFAULT_DYNAMIC_POOL_MIN_CHANNELS = 1;
160160

161161
/**
162162
* Default affinity key lifetime for dynamic channel pool. This is how long to keep an affinity
@@ -204,6 +204,49 @@ public static GcpChannelPoolOptions createDefaultDynamicChannelPoolOptions() {
204204
.build();
205205
}
206206

207+
/**
208+
* Merges user-provided {@link GcpChannelPoolOptions} with Spanner-specific defaults. Any value
209+
* that the user has not explicitly set (i.e. left at the builder's default of 0 or null) will be
210+
* filled in from {@link #createDefaultDynamicChannelPoolOptions()}.
211+
*/
212+
static GcpChannelPoolOptions mergeWithDefaultChannelPoolOptions(
213+
GcpChannelPoolOptions userOptions) {
214+
GcpChannelPoolOptions defaults = createDefaultDynamicChannelPoolOptions();
215+
GcpChannelPoolOptions.Builder merged = GcpChannelPoolOptions.newBuilder(userOptions);
216+
if (userOptions.getMaxSize() <= 0) {
217+
merged.setMaxSize(defaults.getMaxSize());
218+
}
219+
if (userOptions.getMinSize() <= 0) {
220+
merged.setMinSize(defaults.getMinSize());
221+
}
222+
if (userOptions.getInitSize() <= 0) {
223+
merged.setInitSize(defaults.getInitSize());
224+
}
225+
if (userOptions.getMinRpcPerChannel() <= 0
226+
|| userOptions.getMaxRpcPerChannel() <= 0
227+
|| userOptions.getScaleDownInterval() == null
228+
|| userOptions.getScaleDownInterval().isZero()) {
229+
merged.setDynamicScaling(
230+
userOptions.getMinRpcPerChannel() > 0
231+
? userOptions.getMinRpcPerChannel()
232+
: defaults.getMinRpcPerChannel(),
233+
userOptions.getMaxRpcPerChannel() > 0
234+
? userOptions.getMaxRpcPerChannel()
235+
: defaults.getMaxRpcPerChannel(),
236+
userOptions.getScaleDownInterval() != null && !userOptions.getScaleDownInterval().isZero()
237+
? userOptions.getScaleDownInterval()
238+
: defaults.getScaleDownInterval());
239+
}
240+
if (userOptions.getAffinityKeyLifetime() == null
241+
|| userOptions.getAffinityKeyLifetime().isZero()) {
242+
merged.setAffinityKeyLifetime(defaults.getAffinityKeyLifetime());
243+
}
244+
if (userOptions.getCleanupInterval() == null || userOptions.getCleanupInterval().isZero()) {
245+
merged.setCleanupInterval(defaults.getCleanupInterval());
246+
}
247+
return merged.build();
248+
}
249+
207250
private final TransportChannelProvider channelProvider;
208251
private final ChannelEndpointCacheFactory channelEndpointCacheFactory;
209252

@@ -881,21 +924,29 @@ protected SpannerOptions(Builder builder) {
881924

882925
// Dynamic channel pooling is disabled by default.
883926
// It is only enabled when:
884-
// 1. enableDynamicChannelPool() was explicitly called, AND
927+
// 1. enableDynamicChannelPool() was explicitly called (or experimentalHost is set and DCP was
928+
// not explicitly disabled), AND
885929
// 2. grpc-gcp extension is enabled, AND
886930
// 3. numChannels was not explicitly set
887-
if (builder.dynamicChannelPoolEnabled != null && builder.dynamicChannelPoolEnabled) {
888-
// DCP was explicitly enabled, but respect numChannels if set
931+
boolean dcpRequested =
932+
builder.dynamicChannelPoolEnabled != null
933+
? builder.dynamicChannelPoolEnabled
934+
: builder.experimentalHost != null;
935+
if (dcpRequested) {
936+
// DCP was enabled (explicitly or via experimentalHost), but respect numChannels if set
889937
dynamicChannelPoolEnabled = grpcGcpExtensionEnabled && !builder.numChannelsExplicitlySet;
890938
} else {
891939
// DCP is disabled by default, or was explicitly disabled
892940
dynamicChannelPoolEnabled = false;
893941
}
894942

895-
// Use user-provided GcpChannelPoolOptions or create Spanner-specific defaults
943+
// Use user-provided GcpChannelPoolOptions merged with Spanner-specific defaults,
944+
// or create Spanner-specific defaults if no custom options are provided.
945+
// This ensures that dynamic scaling parameters (minRpcPerChannel, maxRpcPerChannel,
946+
// scaleDownInterval) retain their defaults even when the user only customizes pool sizing.
896947
gcpChannelPoolOptions =
897948
builder.gcpChannelPoolOptions != null
898-
? builder.gcpChannelPoolOptions
949+
? mergeWithDefaultChannelPoolOptions(builder.gcpChannelPoolOptions)
899950
: createDefaultDynamicChannelPoolOptions();
900951

901952
autoThrottleAdministrativeRequests = builder.autoThrottleAdministrativeRequests;
@@ -930,7 +981,12 @@ protected SpannerOptions(Builder builder) {
930981
} else {
931982
enableBuiltInMetrics = builder.enableBuiltInMetrics;
932983
}
933-
enableLocationApi = builder.enableLocationApi;
984+
if (builder.experimentalHost != null
985+
&& System.getenv(EXPERIMENTAL_LOCATION_API_ENV_VAR) == null) {
986+
enableLocationApi = true;
987+
} else {
988+
enableLocationApi = builder.enableLocationApi;
989+
}
934990
enableEndToEndTracing = builder.enableEndToEndTracing;
935991
monitoringHost = builder.monitoringHost;
936992
defaultTransactionOptions = builder.defaultTransactionOptions;

0 commit comments

Comments
 (0)