Code review comment: Could there be a scenario where a user does not want to retry on UNAVAILABLE?  This code would always add UNAVAILABLE even if the user specified their own set of retryable codes, and could therefore lead to unexpected behaviour..

Code before review:
private static SpannerAccessor createAndConnect(SpannerConfig spannerConfig) {
SpannerOptions.Builder builder = SpannerOptions.newBuilder();
Set<Code> retryableCodes = new HashSet<>();
retryableCodes.add(Code.UNAVAILABLE);
if (spannerConfig.getRetryableCodes() != null) {
retryableCodes.addAll(spannerConfig.getRetryableCodes());
}
if (spannerConfig.getDataBoostEnabled() != null && spannerConfig.getDataBoostEnabled().get()) {
retryableCodes.add(Code.RESOURCE_EXHAUSTED);
}
builder
.getSpannerStubSettingsBuilder()
.applyToAllUnaryMethods(
input -> {
input.setRetryableCodes(retryableCodes);
return null;
});
builder
.getSpannerStubSettingsBuilder()
.executeStreamingSqlSettings()
.setRetryableCodes(retryableCodes);
UnaryCallSettings.Builder<CommitRequest, CommitResponse> commitSettings =
builder.getSpannerStubSettingsBuilder().commitSettings();
ValueProvider<Duration> commitDeadline = spannerConfig.getCommitDeadline();
if (spannerConfig.getCommitRetrySettings() != null) {
commitSettings.setRetrySettings(spannerConfig.getCommitRetrySettings());
} else if (commitDeadline != null && commitDeadline.get().getMillis() > 0) {
RetrySettings.Builder commitRetrySettingsBuilder =
commitSettings.getRetrySettings().toBuilder();
commitSettings.setRetrySettings(
commitRetrySettingsBuilder
.setTotalTimeout(org.threeten.bp.Duration.ofMillis(commitDeadline.get().getMillis()))
.setMaxRpcTimeout(org.threeten.bp.Duration.ofMillis(commitDeadline.get().getMillis()))
.setInitialRpcTimeout(
org.threeten.bp.Duration.ofMillis(commitDeadline.get().getMillis()))
.build());
}
ServerStreamingCallSettings.Builder<ExecuteSqlRequest, PartialResultSet>
executeStreamingSqlSettings =
builder.getSpannerStubSettingsBuilder().executeStreamingSqlSettings();
if (spannerConfig.getExecuteStreamingSqlRetrySettings() != null) {
executeStreamingSqlSettings.setRetrySettings(
spannerConfig.getExecuteStreamingSqlRetrySettings());
} else {
RetrySettings.Builder executeSqlStreamingRetrySettings =
executeStreamingSqlSettings.getRetrySettings().toBuilder();
executeStreamingSqlSettings.setRetrySettings(
executeSqlStreamingRetrySettings
.setInitialRpcTimeout(org.threeten.bp.Duration.ofMinutes(120))
.setMaxRpcTimeout(org.threeten.bp.Duration.ofMinutes(120))
.setTotalTimeout(org.threeten.bp.Duration.ofMinutes(120))
.build());
}
SpannerStubSettings.Builder spannerStubSettingsBuilder =
builder.getSpannerStubSettingsBuilder();
ValueProvider<Duration> partitionQueryTimeout = spannerConfig.getPartitionQueryTimeout();
if (partitionQueryTimeout != null
&& partitionQueryTimeout.get() != null
&& partitionQueryTimeout.get().getMillis() > 0) {
spannerStubSettingsBuilder
.partitionQuerySettings()
.setSimpleTimeoutNoRetries(
org.threeten.bp.Duration.ofMillis(partitionQueryTimeout.get().getMillis()));
}
ValueProvider<Duration> partitionReadTimeout = spannerConfig.getPartitionReadTimeout();
if (partitionReadTimeout != null
&& partitionReadTimeout.get() != null
&& partitionReadTimeout.get().getMillis() > 0) {
spannerStubSettingsBuilder
.partitionReadSettings()
.setSimpleTimeoutNoRetries(
org.threeten.bp.Duration.ofMillis(partitionReadTimeout.get().getMillis()));
}
ValueProvider<String> projectId = spannerConfig.getProjectId();
if (projectId != null) {
builder.setProjectId(projectId.get());
}
ServiceFactory<Spanner, SpannerOptions> serviceFactory = spannerConfig.getServiceFactory();
if (serviceFactory != null) {
builder.setServiceFactory(serviceFactory);
}
ValueProvider<String> host = spannerConfig.getHost();
if (host != null) {
builder.setHost(host.get());
}
ValueProvider<String> emulatorHost = spannerConfig.getEmulatorHost();
if (emulatorHost != null) {
builder.setEmulatorHost(emulatorHost.get());
if (spannerConfig.getIsLocalChannelProvider() != null
&& spannerConfig.getIsLocalChannelProvider().get()) {
builder.setChannelProvider(LocalChannelProvider.create(emulatorHost.get()));
}
builder.setCredentials(NoCredentials.getInstance());
}
String userAgentString = USER_AGENT_PREFIX + "/" + ReleaseInfo.getReleaseInfo().getVersion();
builder.setHeaderProvider(FixedHeaderProvider.create("user-agent", userAgentString));
ValueProvider<String> databaseRole = spannerConfig.getDatabaseRole();
if (databaseRole != null && databaseRole.get() != null && !databaseRole.get().isEmpty()) {
builder.setDatabaseRole(databaseRole.get());
}
SpannerOptions options = builder.build();
Spanner spanner = options.getService();
String instanceId = spannerConfig.getInstanceId().get();
String databaseId = spannerConfig.getDatabaseId().get();
DatabaseClient databaseClient =
spanner.getDatabaseClient(DatabaseId.of(options.getProjectId(), instanceId, databaseId));
BatchClient batchClient =
spanner.getBatchClient(DatabaseId.of(options.getProjectId(), instanceId, databaseId));
DatabaseAdminClient databaseAdminClient = spanner.getDatabaseAdminClient();
return new SpannerAccessor(
spanner, databaseClient, databaseAdminClient, batchClient, spannerConfig);
}

Line under review: retryableCodes.add(Code.UNAVAILABLE);

Code after addressing the review:
private static SpannerAccessor createAndConnect(SpannerConfig spannerConfig) {
SpannerOptions.Builder builder = SpannerOptions.newBuilder();
Set<Code> retryableCodes = new HashSet<>();
if (spannerConfig.getRetryableCodes() != null) {
retryableCodes.addAll(spannerConfig.getRetryableCodes());
}
if (spannerConfig.getDataBoostEnabled() != null && spannerConfig.getDataBoostEnabled().get()) {
retryableCodes.add(Code.RESOURCE_EXHAUSTED);
}
Set<Code> unaryMethodRetryableCodes = new HashSet<>(retryableCodes);
unaryMethodRetryableCodes.addAll(
builder.getSpannerStubSettingsBuilder().getSessionSettings().getRetryableCodes());
builder
.getSpannerStubSettingsBuilder()
.applyToAllUnaryMethods(
input -> {
input.setRetryableCodes(unaryMethodRetryableCodes);
return null;
});
Set<Code> streamingMethodRetryableCodes = new HashSet<>(retryableCodes);
streamingMethodRetryableCodes.addAll(
builder.getSpannerStubSettingsBuilder().executeStreamingSqlSettings().getRetryableCodes());
builder
.getSpannerStubSettingsBuilder()
.executeStreamingSqlSettings()
.setRetryableCodes(streamingMethodRetryableCodes);
builder
.getSpannerStubSettingsBuilder()
.streamingReadSettings()
.setRetryableCodes(streamingMethodRetryableCodes);
UnaryCallSettings.Builder<CommitRequest, CommitResponse> commitSettings =
builder.getSpannerStubSettingsBuilder().commitSettings();
ValueProvider<Duration> commitDeadline = spannerConfig.getCommitDeadline();
if (spannerConfig.getCommitRetrySettings() != null) {
commitSettings.setRetrySettings(spannerConfig.getCommitRetrySettings());
} else if (commitDeadline != null && commitDeadline.get().getMillis() > 0) {
RetrySettings.Builder commitRetrySettingsBuilder =
commitSettings.getRetrySettings().toBuilder();
commitSettings.setRetrySettings(
commitRetrySettingsBuilder
.setTotalTimeout(org.threeten.bp.Duration.ofMillis(commitDeadline.get().getMillis()))
.setMaxRpcTimeout(org.threeten.bp.Duration.ofMillis(commitDeadline.get().getMillis()))
.setInitialRpcTimeout(
org.threeten.bp.Duration.ofMillis(commitDeadline.get().getMillis()))
.build());
}
ServerStreamingCallSettings.Builder<ExecuteSqlRequest, PartialResultSet>
executeStreamingSqlSettings =
builder.getSpannerStubSettingsBuilder().executeStreamingSqlSettings();
if (spannerConfig.getExecuteStreamingSqlRetrySettings() != null) {
executeStreamingSqlSettings.setRetrySettings(
spannerConfig.getExecuteStreamingSqlRetrySettings());
} else {
RetrySettings.Builder executeSqlStreamingRetrySettings =
executeStreamingSqlSettings.getRetrySettings().toBuilder();
executeStreamingSqlSettings.setRetrySettings(
executeSqlStreamingRetrySettings
.setInitialRpcTimeout(org.threeten.bp.Duration.ofMinutes(120))
.setMaxRpcTimeout(org.threeten.bp.Duration.ofMinutes(120))
.setTotalTimeout(org.threeten.bp.Duration.ofMinutes(120))
.build());
}
SpannerStubSettings.Builder spannerStubSettingsBuilder =
builder.getSpannerStubSettingsBuilder();
ValueProvider<Duration> partitionQueryTimeout = spannerConfig.getPartitionQueryTimeout();
if (partitionQueryTimeout != null
&& partitionQueryTimeout.get() != null
&& partitionQueryTimeout.get().getMillis() > 0) {
spannerStubSettingsBuilder
.partitionQuerySettings()
.setSimpleTimeoutNoRetries(
org.threeten.bp.Duration.ofMillis(partitionQueryTimeout.get().getMillis()));
}
ValueProvider<Duration> partitionReadTimeout = spannerConfig.getPartitionReadTimeout();
if (partitionReadTimeout != null
&& partitionReadTimeout.get() != null
&& partitionReadTimeout.get().getMillis() > 0) {
spannerStubSettingsBuilder
.partitionReadSettings()
.setSimpleTimeoutNoRetries(
org.threeten.bp.Duration.ofMillis(partitionReadTimeout.get().getMillis()));
}
ValueProvider<String> projectId = spannerConfig.getProjectId();
if (projectId != null) {
builder.setProjectId(projectId.get());
}
ServiceFactory<Spanner, SpannerOptions> serviceFactory = spannerConfig.getServiceFactory();
if (serviceFactory != null) {
builder.setServiceFactory(serviceFactory);
}
ValueProvider<String> host = spannerConfig.getHost();
if (host != null) {
builder.setHost(host.get());
}
ValueProvider<String> emulatorHost = spannerConfig.getEmulatorHost();
if (emulatorHost != null) {
builder.setEmulatorHost(emulatorHost.get());
if (spannerConfig.getIsLocalChannelProvider() != null
&& spannerConfig.getIsLocalChannelProvider().get()) {
builder.setChannelProvider(LocalChannelProvider.create(emulatorHost.get()));
}
builder.setCredentials(NoCredentials.getInstance());
}
String userAgentString = USER_AGENT_PREFIX + "/" + ReleaseInfo.getReleaseInfo().getVersion();
builder.setHeaderProvider(FixedHeaderProvider.create("user-agent", userAgentString));
ValueProvider<String> databaseRole = spannerConfig.getDatabaseRole();
if (databaseRole != null && databaseRole.get() != null && !databaseRole.get().isEmpty()) {
builder.setDatabaseRole(databaseRole.get());
}
SpannerOptions options = builder.build();
Spanner spanner = options.getService();
String instanceId = spannerConfig.getInstanceId().get();
String databaseId = spannerConfig.getDatabaseId().get();
DatabaseClient databaseClient =
spanner.getDatabaseClient(DatabaseId.of(options.getProjectId(), instanceId, databaseId));
BatchClient batchClient =
spanner.getBatchClient(DatabaseId.of(options.getProjectId(), instanceId, databaseId));
DatabaseAdminClient databaseAdminClient = spanner.getDatabaseAdminClient();
return new SpannerAccessor(
spanner, databaseClient, databaseAdminClient, batchClient, spannerConfig);
}