22
22
import com .google .api .gax .paging .Page ;
23
23
import com .google .api .gax .retrying .RetrySettings ;
24
24
import com .google .api .gax .rpc .DeadlineExceededException ;
25
- import com .google .api .gax .rpc .TransportChannelProvider ;
26
25
import com .google .api .gax .rpc .UnavailableException ;
27
- import com .google .auth .Credentials ;
28
- import com .google .auth .oauth2 .GoogleCredentials ;
29
26
import com .google .cloud .ByteArray ;
30
27
import com .google .cloud .Date ;
31
- import com .google .cloud .NoCredentials ;
32
28
import com .google .cloud .Timestamp ;
33
29
import com .google .cloud .spanner .Backup ;
34
30
import com .google .cloud .spanner .BatchClient ;
52
48
import com .google .cloud .spanner .Mutation ;
53
49
import com .google .cloud .spanner .Mutation .WriteBuilder ;
54
50
import com .google .cloud .spanner .Options ;
51
+ import com .google .cloud .spanner .Options .RpcPriority ;
55
52
import com .google .cloud .spanner .Partition ;
56
53
import com .google .cloud .spanner .PartitionOptions ;
57
54
import com .google .cloud .spanner .ReadContext ;
128
125
import com .google .spanner .executor .v1 .MutationAction .Mod ;
129
126
import com .google .spanner .executor .v1 .MutationAction .UpdateArgs ;
130
127
import com .google .spanner .executor .v1 .OperationResponse ;
128
+ import com .google .spanner .executor .v1 .PartitionedUpdateAction ;
129
+ import com .google .spanner .executor .v1 .PartitionedUpdateAction .ExecutePartitionedUpdateOptions ;
131
130
import com .google .spanner .executor .v1 .QueryAction ;
132
131
import com .google .spanner .executor .v1 .ReadAction ;
133
132
import com .google .spanner .executor .v1 .RestoreCloudDatabaseAction ;
145
144
import com .google .spanner .v1 .TypeCode ;
146
145
import io .grpc .Status ;
147
146
import io .grpc .stub .StreamObserver ;
148
- import java .io .ByteArrayInputStream ;
149
- import java .io .File ;
150
147
import java .io .IOException ;
151
148
import java .io .ObjectInputStream ;
152
149
import java .io .ObjectOutputStream ;
165
162
import java .util .logging .Logger ;
166
163
import java .util .stream .Collectors ;
167
164
import javax .annotation .Nullable ;
168
- import org .apache .commons .io .FileUtils ;
169
165
import org .jetbrains .annotations .NotNull ;
170
166
import org .threeten .bp .Duration ;
171
167
import org .threeten .bp .LocalDate ;
@@ -747,20 +743,6 @@ private synchronized Spanner getClient() throws IOException {
747
743
748
744
// Return the spanner client, create one if not exists.
749
745
private synchronized Spanner getClient (long timeoutSeconds ) throws IOException {
750
- // Create a cloud spanner client
751
- Credentials credentials ;
752
- if (WorkerProxy .serviceKeyFile .isEmpty ()) {
753
- credentials = NoCredentials .getInstance ();
754
- } else {
755
- credentials =
756
- GoogleCredentials .fromStream (
757
- new ByteArrayInputStream (
758
- FileUtils .readFileToByteArray (new File (WorkerProxy .serviceKeyFile ))),
759
- HTTP_TRANSPORT_FACTORY );
760
- }
761
-
762
- TransportChannelProvider channelProvider =
763
- CloudUtil .newChannelProviderHelper (WorkerProxy .spannerPort );
764
746
765
747
Duration rpcTimeout = Duration .ofHours (1L );
766
748
if (timeoutSeconds > 0 ) {
@@ -779,12 +761,7 @@ private synchronized Spanner getClient(long timeoutSeconds) throws IOException {
779
761
780
762
// Cloud Spanner Client does not support global retry settings,
781
763
// Thus, we need to add retry settings to each individual stub.
782
- SpannerOptions .Builder optionsBuilder =
783
- SpannerOptions .newBuilder ()
784
- .setProjectId (PROJECT_ID )
785
- .setHost (HOST_PREFIX + WorkerProxy .spannerPort )
786
- .setCredentials (credentials )
787
- .setChannelProvider (channelProvider );
764
+ SpannerOptions .Builder optionsBuilder = SpannerOptions .newBuilder ().setProjectId (PROJECT_ID );
788
765
789
766
SpannerStubSettings .Builder stubSettingsBuilder =
790
767
optionsBuilder .getSpannerStubSettingsBuilder ();
@@ -886,6 +863,13 @@ private Status executeAction(
886
863
} else if (action .hasExecutePartition ()) {
887
864
return executeExecutePartition (
888
865
action .getExecutePartition (), outcomeSender , executionContext );
866
+ } else if (action .hasPartitionedUpdate ()) {
867
+ if (dbPath == null ) {
868
+ throw SpannerExceptionFactory .newSpannerException (
869
+ ErrorCode .INVALID_ARGUMENT , "Database path must be set for this action" );
870
+ }
871
+ DatabaseClient dbClient = getClient ().getDatabaseClient (DatabaseId .of (dbPath ));
872
+ return executePartitionedUpdate (action .getPartitionedUpdate (), dbClient , outcomeSender );
889
873
} else if (action .hasCloseBatchTxn ()) {
890
874
return executeCloseBatchTxn (action .getCloseBatchTxn (), outcomeSender , executionContext );
891
875
} else if (action .hasExecuteChangeStreamQuery ()) {
@@ -1974,6 +1958,33 @@ private Status executeExecutePartition(
1974
1958
}
1975
1959
}
1976
1960
1961
+ /** Execute a partitioned update which runs different partitions in parallel. */
1962
+ private Status executePartitionedUpdate (
1963
+ PartitionedUpdateAction action , DatabaseClient dbClient , OutcomeSender sender ) {
1964
+ try {
1965
+ ExecutePartitionedUpdateOptions options = action .getOptions ();
1966
+ Long count =
1967
+ dbClient .executePartitionedUpdate (
1968
+ Statement .of (action .getUpdate ().getSql ()),
1969
+ Options .tag (options .getTag ()),
1970
+ Options .priority (RpcPriority .getEnumFromProto (options .getRpcPriority ())));
1971
+ SpannerActionOutcome outcome =
1972
+ SpannerActionOutcome .newBuilder ()
1973
+ .setStatus (toProto (Status .OK ))
1974
+ .addDmlRowsModified (count )
1975
+ .build ();
1976
+ sender .sendOutcome (outcome );
1977
+ return sender .finishWithOK ();
1978
+ } catch (SpannerException e ) {
1979
+ return sender .finishWithError (toStatus (e ));
1980
+ } catch (Exception e ) {
1981
+ return sender .finishWithError (
1982
+ toStatus (
1983
+ SpannerExceptionFactory .newSpannerException (
1984
+ ErrorCode .INVALID_ARGUMENT , "Unexpected error: " + e .getMessage ())));
1985
+ }
1986
+ }
1987
+
1977
1988
/** Build a child partition record proto out of childPartitionRecord returned by client. */
1978
1989
private ChildPartitionsRecord buildChildPartitionRecord (Struct childPartitionRecord )
1979
1990
throws Exception {
0 commit comments