Skip to content

Commit

Permalink
Merge branch 'googleapis:main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
arpan14 authored Apr 2, 2024
2 parents 8fcf900 + 54bef01 commit ab1c8ee
Show file tree
Hide file tree
Showing 17 changed files with 743 additions and 279 deletions.
12 changes: 12 additions & 0 deletions google-cloud-spanner/clirr-ignored-differences.xml
Original file line number Diff line number Diff line change
Expand Up @@ -631,4 +631,16 @@
<className>com/google/cloud/spanner/connection/Connection</className>
<method>void setDirectedRead(com.google.spanner.v1.DirectedReadOptions)</method>
</difference>

<!-- Added MaxCommitDelay -->
<difference>
<differenceType>7012</differenceType>
<className>com/google/cloud/spanner/connection/Connection</className>
<method>java.time.Duration getMaxCommitDelay()</method>
</difference>
<difference>
<differenceType>7012</differenceType>
<className>com/google/cloud/spanner/connection/Connection</className>
<method>void setMaxCommitDelay(java.time.Duration)</method>
</difference>
</differences>
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
import com.google.spanner.v1.DirectedReadOptions;
import com.google.spanner.v1.ExecuteBatchDmlRequest;
import com.google.spanner.v1.ResultSetStats;
import java.time.Duration;
import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.ExecutionException;
Expand Down Expand Up @@ -556,6 +557,16 @@ default String getOptimizerStatisticsPackage() {
/** @return true if this connection requests commit statistics from Cloud Spanner */
boolean isReturnCommitStats();

/** Sets the max_commit_delay that will be applied to commit requests from this connection. */
default void setMaxCommitDelay(Duration maxCommitDelay) {
throw new UnsupportedOperationException("Unimplemented");
}

/** Returns the max_commit_delay that will be applied to commit requests from this connection. */
default Duration getMaxCommitDelay() {
throw new UnsupportedOperationException("Unimplemented");
}

/**
* Sets the priority to use for RPCs executed by this connection..
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
import com.google.spanner.v1.DirectedReadOptions;
import com.google.spanner.v1.ExecuteSqlRequest.QueryOptions;
import com.google.spanner.v1.ResultSetStats;
import java.time.Duration;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
Expand Down Expand Up @@ -245,6 +246,8 @@ static UnitOfWorkType of(TransactionMode transactionMode) {
private String transactionTag;
private String statementTag;

private Duration maxCommitDelay;

/** Create a connection and register it in the SpannerPool. */
ConnectionImpl(ConnectionOptions options) {
Preconditions.checkNotNull(options);
Expand Down Expand Up @@ -273,6 +276,7 @@ static UnitOfWorkType of(TransactionMode transactionMode) {
this.autoPartitionMode = options.isAutoPartitionMode();
this.maxPartitions = options.getMaxPartitions();
this.maxPartitionedParallelism = options.getMaxPartitionedParallelism();
this.maxCommitDelay = options.getMaxCommitDelay();
this.ddlClient = createDdlClient();
setDefaultTransactionOptions();
}
Expand Down Expand Up @@ -791,6 +795,18 @@ public boolean isReturnCommitStats() {
return this.returnCommitStats;
}

@Override
public void setMaxCommitDelay(Duration maxCommitDelay) {
ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG);
this.maxCommitDelay = maxCommitDelay;
}

@Override
public Duration getMaxCommitDelay() {
ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG);
return this.maxCommitDelay;
}

@Override
public void setDelayTransactionStartUntilFirstWrite(
boolean delayTransactionStartUntilFirstWrite) {
Expand Down Expand Up @@ -1614,6 +1630,7 @@ UnitOfWork createNewUnitOfWork(boolean isInternalMetadataQuery) {
.setReadOnlyStaleness(readOnlyStaleness)
.setAutocommitDmlMode(autocommitDmlMode)
.setReturnCommitStats(returnCommitStats)
.setMaxCommitDelay(maxCommitDelay)
.setStatementTimeout(statementTimeout)
.withStatementExecutor(statementExecutor)
.build();
Expand All @@ -1636,6 +1653,7 @@ UnitOfWork createNewUnitOfWork(boolean isInternalMetadataQuery) {
.setRetryAbortsInternally(retryAbortsInternally)
.setSavepointSupport(savepointSupport)
.setReturnCommitStats(returnCommitStats)
.setMaxCommitDelay(maxCommitDelay)
.setTransactionRetryListeners(transactionRetryListeners)
.setStatementTimeout(statementTimeout)
.withStatementExecutor(statementExecutor)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.time.Duration;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
Expand Down Expand Up @@ -175,6 +176,7 @@ public String[] getValidValues() {
private static final String DEFAULT_MIN_SESSIONS = null;
private static final String DEFAULT_MAX_SESSIONS = null;
private static final String DEFAULT_NUM_CHANNELS = null;
static final String DEFAULT_ENDPOINT = null;
private static final String DEFAULT_CHANNEL_PROVIDER = null;
private static final String DEFAULT_DATABASE_ROLE = null;
private static final String DEFAULT_USER_AGENT = null;
Expand Down Expand Up @@ -234,6 +236,8 @@ public String[] getValidValues() {
public static final String MAX_SESSIONS_PROPERTY_NAME = "maxSessions";
/** Name of the 'numChannels' connection property. */
public static final String NUM_CHANNELS_PROPERTY_NAME = "numChannels";
/** Name of the 'endpoint' connection property. */
public static final String ENDPOINT_PROPERTY_NAME = "endpoint";
/** Name of the 'channelProvider' connection property. */
public static final String CHANNEL_PROVIDER_PROPERTY_NAME = "channelProvider";

Expand Down Expand Up @@ -332,6 +336,12 @@ private static String generateGuardedConnectionPropertyError(
ConnectionProperty.createStringProperty(
NUM_CHANNELS_PROPERTY_NAME,
"The number of gRPC channels to use to communicate with Cloud Spanner. The default is 4."),
ConnectionProperty.createStringProperty(
ENDPOINT_PROPERTY_NAME,
"The endpoint that the JDBC driver should connect to. "
+ "The default is the default Spanner production endpoint when autoConfigEmulator=false, "
+ "and the default Spanner emulator endpoint (localhost:9010) when autoConfigEmulator=true. "
+ "This property takes precedence over any host name at the start of the connection URL."),
ConnectionProperty.createStringProperty(
CHANNEL_PROVIDER_PROPERTY_NAME,
"The name of the channel provider class. The name must reference an implementation of ExternalChannelProvider. If this property is not set, the connection will use the default grpc channel provider."),
Expand All @@ -348,6 +358,9 @@ private static String generateGuardedConnectionPropertyError(
ConnectionProperty.createStringProperty(
OPTIMIZER_STATISTICS_PACKAGE_PROPERTY_NAME, ""),
ConnectionProperty.createBooleanProperty("returnCommitStats", "", false),
ConnectionProperty.createStringProperty(
"maxCommitDelay",
"The maximum commit delay in milliseconds that should be applied to commit requests from this connection."),
ConnectionProperty.createBooleanProperty(
"autoConfigEmulator",
"Automatically configure the connection to try to connect to the Cloud Spanner emulator (true/false). "
Expand Down Expand Up @@ -680,6 +693,7 @@ public static Builder newBuilder() {
private final String userAgent;
private final QueryOptions queryOptions;
private final boolean returnCommitStats;
private final Long maxCommitDelay;
private final boolean autoConfigEmulator;
private final Dialect dialect;
private final RpcPriority rpcPriority;
Expand Down Expand Up @@ -735,10 +749,13 @@ private ConnectionOptions(Builder builder) {
queryOptionsBuilder.setOptimizerStatisticsPackage(parseOptimizerStatisticsPackage(this.uri));
this.queryOptions = queryOptionsBuilder.build();
this.returnCommitStats = parseReturnCommitStats(this.uri);
this.maxCommitDelay = parseMaxCommitDelay(this.uri);
this.autoConfigEmulator = parseAutoConfigEmulator(this.uri);
this.dialect = parseDialect(this.uri);
this.usePlainText = this.autoConfigEmulator || parseUsePlainText(this.uri);
this.host = determineHost(matcher, autoConfigEmulator, usePlainText, System.getenv());
this.host =
determineHost(
matcher, parseEndpoint(this.uri), autoConfigEmulator, usePlainText, System.getenv());
this.rpcPriority = parseRPCPriority(this.uri);
this.delayTransactionStartUntilFirstWrite = parseDelayTransactionStartUntilFirstWrite(this.uri);
this.trackSessionLeaks = parseTrackSessionLeaks(this.uri);
Expand Down Expand Up @@ -829,10 +846,12 @@ private ConnectionOptions(Builder builder) {
@VisibleForTesting
static String determineHost(
Matcher matcher,
String endpoint,
boolean autoConfigEmulator,
boolean usePlainText,
Map<String, String> environment) {
if (matcher.group(Builder.HOST_GROUP) == null) {
String host;
if (Objects.equals(endpoint, DEFAULT_ENDPOINT) && matcher.group(Builder.HOST_GROUP) == null) {
if (autoConfigEmulator) {
if (Strings.isNullOrEmpty(environment.get(SPANNER_EMULATOR_HOST_ENV_VAR))) {
return DEFAULT_EMULATOR_HOST;
Expand All @@ -842,13 +861,18 @@ static String determineHost(
} else {
return DEFAULT_HOST;
}
} else if (!Objects.equals(endpoint, DEFAULT_ENDPOINT)) {
// Add '//' at the start of the endpoint to conform to the standard URL specification.
host = "//" + endpoint;
} else {
if (usePlainText) {
return PLAIN_TEXT_PROTOCOL + matcher.group(Builder.HOST_GROUP);
} else {
return HOST_PROTOCOL + matcher.group(Builder.HOST_GROUP);
}
// The leading '//' is already included in the regex for the connection URL, so we don't need
// to add the leading '//' to the host name here.
host = matcher.group(Builder.HOST_GROUP);
}
if (usePlainText) {
return PLAIN_TEXT_PROTOCOL + host;
}
return HOST_PROTOCOL + host;
}

private static Integer parseIntegerProperty(String propertyName, String value) {
Expand Down Expand Up @@ -1013,6 +1037,11 @@ static String parseNumChannels(String uri) {
return value != null ? value : DEFAULT_NUM_CHANNELS;
}

private static String parseEndpoint(String uri) {
String value = parseUriProperty(uri, ENDPOINT_PROPERTY_NAME);
return value != null ? value : DEFAULT_ENDPOINT;
}

@VisibleForTesting
static String parseChannelProvider(String uri) {
String value = parseUriProperty(uri, CHANNEL_PROVIDER_PROPERTY_NAME);
Expand Down Expand Up @@ -1051,6 +1080,27 @@ static boolean parseReturnCommitStats(String uri) {
return Boolean.parseBoolean(value);
}

@VisibleForTesting
static Long parseMaxCommitDelay(String uri) {
String value = parseUriProperty(uri, "maxCommitDelay");
try {
Long millis = value == null ? null : Long.valueOf(value);
if (millis != null && millis < 0L) {
throw SpannerExceptionFactory.newSpannerException(
ErrorCode.INVALID_ARGUMENT, "maxCommitDelay must be >=0");
}
return millis;
} catch (NumberFormatException numberFormatException) {
throw SpannerExceptionFactory.newSpannerException(
ErrorCode.INVALID_ARGUMENT,
"Invalid value for maxCommitDelay: "
+ value
+ "\n"
+ "The value must be a positive integer indicating the number of "
+ "milliseconds to use as the max delay.");
}
}

static boolean parseAutoConfigEmulator(String uri) {
String value = parseUriProperty(uri, "autoConfigEmulator");
return Boolean.parseBoolean(value);
Expand Down Expand Up @@ -1382,6 +1432,11 @@ public boolean isReturnCommitStats() {
return returnCommitStats;
}

/** The max_commit_delay that should be applied to commit operations on this connection. */
public Duration getMaxCommitDelay() {
return maxCommitDelay == null ? null : Duration.ofMillis(maxCommitDelay);
}

/**
* Whether connections created by this {@link ConnectionOptions} will automatically try to connect
* to the emulator using the default host/port of the emulator, and automatically create the
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,10 @@ interface ConnectionStatementExecutor {

StatementResult statementShowReturnCommitStats();

StatementResult statementSetMaxCommitDelay(Duration maxCommitDelay);

StatementResult statementShowMaxCommitDelay();

StatementResult statementSetDelayTransactionStartUntilFirstWrite(
Boolean delayTransactionStartUntilFirstWrite);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import static com.google.cloud.spanner.connection.StatementResult.ClientSideStatementType.SET_DEFAULT_TRANSACTION_ISOLATION;
import static com.google.cloud.spanner.connection.StatementResult.ClientSideStatementType.SET_DELAY_TRANSACTION_START_UNTIL_FIRST_WRITE;
import static com.google.cloud.spanner.connection.StatementResult.ClientSideStatementType.SET_DIRECTED_READ;
import static com.google.cloud.spanner.connection.StatementResult.ClientSideStatementType.SET_MAX_COMMIT_DELAY;
import static com.google.cloud.spanner.connection.StatementResult.ClientSideStatementType.SET_MAX_PARTITIONED_PARALLELISM;
import static com.google.cloud.spanner.connection.StatementResult.ClientSideStatementType.SET_MAX_PARTITIONS;
import static com.google.cloud.spanner.connection.StatementResult.ClientSideStatementType.SET_OPTIMIZER_STATISTICS_PACKAGE;
Expand All @@ -51,6 +52,7 @@
import static com.google.cloud.spanner.connection.StatementResult.ClientSideStatementType.SHOW_DATA_BOOST_ENABLED;
import static com.google.cloud.spanner.connection.StatementResult.ClientSideStatementType.SHOW_DELAY_TRANSACTION_START_UNTIL_FIRST_WRITE;
import static com.google.cloud.spanner.connection.StatementResult.ClientSideStatementType.SHOW_DIRECTED_READ;
import static com.google.cloud.spanner.connection.StatementResult.ClientSideStatementType.SHOW_MAX_COMMIT_DELAY;
import static com.google.cloud.spanner.connection.StatementResult.ClientSideStatementType.SHOW_MAX_PARTITIONED_PARALLELISM;
import static com.google.cloud.spanner.connection.StatementResult.ClientSideStatementType.SHOW_MAX_PARTITIONS;
import static com.google.cloud.spanner.connection.StatementResult.ClientSideStatementType.SHOW_OPTIMIZER_STATISTICS_PACKAGE;
Expand Down Expand Up @@ -343,6 +345,26 @@ public StatementResult statementShowReturnCommitStats() {
SHOW_RETURN_COMMIT_STATS);
}

@Override
public StatementResult statementSetMaxCommitDelay(Duration duration) {
getConnection()
.setMaxCommitDelay(
duration == null || duration.equals(Duration.getDefaultInstance())
? null
: java.time.Duration.ofSeconds(duration.getSeconds(), duration.getNanos()));
return noResult(SET_MAX_COMMIT_DELAY);
}

@Override
public StatementResult statementShowMaxCommitDelay() {
return resultSet(
"MAX_COMMIT_DELAY",
getConnection().getMaxCommitDelay() == null
? null
: getConnection().getMaxCommitDelay().toMillis() + "ms",
SHOW_MAX_COMMIT_DELAY);
}

@Override
public StatementResult statementSetDelayTransactionStartUntilFirstWrite(
Boolean delayTransactionStartUntilFirstWrite) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
import com.google.common.collect.Iterables;
import com.google.common.util.concurrent.MoreExecutors;
import com.google.spanner.v1.SpannerGrpc;
import java.time.Duration;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
Expand Down Expand Up @@ -111,6 +112,7 @@ static class Builder extends AbstractMultiUseTransaction.Builder<Builder, ReadWr
private Boolean retryAbortsInternally;
private boolean delayTransactionStartUntilFirstWrite;
private boolean returnCommitStats;
private Duration maxCommitDelay;
private SavepointSupport savepointSupport;
private List<TransactionRetryListener> transactionRetryListeners;

Expand All @@ -137,6 +139,11 @@ Builder setReturnCommitStats(boolean returnCommitStats) {
return this;
}

Builder setMaxCommitDelay(Duration maxCommitDelay) {
this.maxCommitDelay = maxCommitDelay;
return this;
}

Builder setSavepointSupport(SavepointSupport savepointSupport) {
this.savepointSupport = savepointSupport;
return this;
Expand Down Expand Up @@ -180,6 +187,9 @@ private TransactionOption[] extractOptions(Builder builder) {
if (builder.returnCommitStats) {
numOptions++;
}
if (builder.maxCommitDelay != null) {
numOptions++;
}
if (this.transactionTag != null) {
numOptions++;
}
Expand All @@ -191,6 +201,9 @@ private TransactionOption[] extractOptions(Builder builder) {
if (builder.returnCommitStats) {
options[index++] = Options.commitStats();
}
if (builder.maxCommitDelay != null) {
options[index++] = Options.maxCommitDelay(builder.maxCommitDelay);
}
if (this.transactionTag != null) {
options[index++] = Options.tag(this.transactionTag);
}
Expand Down
Loading

0 comments on commit ab1c8ee

Please sign in to comment.