Skip to content

Commit bd678c9

Browse files
committed
refactor SpannerImpl: move DatabaseAdminClientImpl to separate file
1 parent 81f9c46 commit bd678c9

3 files changed

Lines changed: 194 additions & 157 deletions

File tree

Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
/*
2+
* Copyright 2019 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.google.cloud.spanner;
18+
19+
import com.google.api.core.ApiFunction;
20+
import com.google.api.gax.grpc.ProtoOperationTransformers;
21+
import com.google.api.gax.longrunning.OperationFuture;
22+
import com.google.api.gax.longrunning.OperationFutureImpl;
23+
import com.google.api.gax.longrunning.OperationSnapshot;
24+
import com.google.api.gax.paging.Page;
25+
import com.google.cloud.spanner.Options.ListOption;
26+
import com.google.cloud.spanner.SpannerImpl.PageFetcher;
27+
import com.google.cloud.spanner.spi.v1.SpannerRpc;
28+
import com.google.cloud.spanner.spi.v1.SpannerRpc.Paginated;
29+
import com.google.common.base.Preconditions;
30+
import com.google.protobuf.Empty;
31+
import com.google.spanner.admin.database.v1.CreateDatabaseMetadata;
32+
import com.google.spanner.admin.database.v1.UpdateDatabaseDdlMetadata;
33+
import java.util.List;
34+
import java.util.UUID;
35+
import java.util.concurrent.Callable;
36+
import javax.annotation.Nullable;
37+
38+
/** Default implementation of {@link DatabaseAdminClient}. */
39+
class DatabaseAdminClientImpl implements DatabaseAdminClient {
40+
private final String projectId;
41+
private final SpannerRpc rpc;
42+
43+
DatabaseAdminClientImpl(String projectId, SpannerRpc rpc) {
44+
this.projectId = projectId;
45+
this.rpc = rpc;
46+
}
47+
48+
/** Generates a random operation id for long-running database operations. */
49+
private static String randomOperationId() {
50+
UUID uuid = UUID.randomUUID();
51+
return ("r" + uuid.toString()).replace("-", "_");
52+
}
53+
54+
@Override
55+
public OperationFuture<Database, CreateDatabaseMetadata> createDatabase(
56+
String instanceId, String databaseId, Iterable<String> statements) throws SpannerException {
57+
// CreateDatabase() is not idempotent, so we're not retrying this request.
58+
String instanceName = getInstanceName(instanceId);
59+
String createStatement = "CREATE DATABASE `" + databaseId + "`";
60+
OperationFuture<com.google.spanner.admin.database.v1.Database, CreateDatabaseMetadata>
61+
rawOperationFuture = rpc.createDatabase(instanceName, createStatement, statements);
62+
return new OperationFutureImpl<Database, CreateDatabaseMetadata>(
63+
rawOperationFuture.getPollingFuture(),
64+
rawOperationFuture.getInitialFuture(),
65+
new ApiFunction<OperationSnapshot, Database>() {
66+
@Override
67+
public Database apply(OperationSnapshot snapshot) {
68+
return Database.fromProto(
69+
ProtoOperationTransformers.ResponseTransformer.create(
70+
com.google.spanner.admin.database.v1.Database.class)
71+
.apply(snapshot),
72+
DatabaseAdminClientImpl.this);
73+
}
74+
},
75+
ProtoOperationTransformers.MetadataTransformer.create(CreateDatabaseMetadata.class),
76+
new ApiFunction<Exception, Database>() {
77+
@Override
78+
public Database apply(Exception e) {
79+
throw SpannerExceptionFactory.newSpannerException(e);
80+
}
81+
});
82+
}
83+
84+
@Override
85+
public Database getDatabase(String instanceId, String databaseId) throws SpannerException {
86+
final String dbName = getDatabaseName(instanceId, databaseId);
87+
Callable<Database> callable =
88+
new Callable<Database>() {
89+
@Override
90+
public Database call() throws Exception {
91+
return Database.fromProto(rpc.getDatabase(dbName), DatabaseAdminClientImpl.this);
92+
}
93+
};
94+
return SpannerImpl.runWithRetries(callable);
95+
}
96+
97+
@Override
98+
public OperationFuture<Void, UpdateDatabaseDdlMetadata> updateDatabaseDdl(
99+
final String instanceId,
100+
final String databaseId,
101+
final Iterable<String> statements,
102+
@Nullable String operationId)
103+
throws SpannerException {
104+
final String dbName = getDatabaseName(instanceId, databaseId);
105+
final String opId = operationId != null ? operationId : randomOperationId();
106+
OperationFuture<Empty, UpdateDatabaseDdlMetadata> rawOperationFuture =
107+
rpc.updateDatabaseDdl(dbName, statements, opId);
108+
return new OperationFutureImpl<Void, UpdateDatabaseDdlMetadata>(
109+
rawOperationFuture.getPollingFuture(),
110+
rawOperationFuture.getInitialFuture(),
111+
new ApiFunction<OperationSnapshot, Void>() {
112+
@Override
113+
public Void apply(OperationSnapshot snapshot) {
114+
ProtoOperationTransformers.ResponseTransformer.create(Empty.class).apply(snapshot);
115+
return null;
116+
}
117+
},
118+
ProtoOperationTransformers.MetadataTransformer.create(UpdateDatabaseDdlMetadata.class),
119+
new ApiFunction<Exception, Void>() {
120+
@Override
121+
public Void apply(Exception e) {
122+
throw SpannerExceptionFactory.newSpannerException(e);
123+
}
124+
});
125+
}
126+
127+
@Override
128+
public void dropDatabase(String instanceId, String databaseId) throws SpannerException {
129+
final String dbName = getDatabaseName(instanceId, databaseId);
130+
Callable<Void> callable =
131+
new Callable<Void>() {
132+
@Override
133+
public Void call() throws Exception {
134+
rpc.dropDatabase(dbName);
135+
return null;
136+
}
137+
};
138+
SpannerImpl.runWithRetries(callable);
139+
}
140+
141+
@Override
142+
public List<String> getDatabaseDdl(String instanceId, String databaseId) {
143+
final String dbName = getDatabaseName(instanceId, databaseId);
144+
Callable<List<String>> callable =
145+
new Callable<List<String>>() {
146+
@Override
147+
public List<String> call() throws Exception {
148+
return rpc.getDatabaseDdl(dbName);
149+
}
150+
};
151+
return SpannerImpl.runWithRetries(callable);
152+
}
153+
154+
@Override
155+
public Page<Database> listDatabases(String instanceId, ListOption... options) {
156+
final String instanceName = getInstanceName(instanceId);
157+
final Options listOptions = Options.fromListOptions(options);
158+
Preconditions.checkArgument(
159+
!listOptions.hasFilter(), "Filter option is not support by" + "listDatabases");
160+
final int pageSize = listOptions.hasPageSize() ? listOptions.pageSize() : 0;
161+
PageFetcher<Database, com.google.spanner.admin.database.v1.Database> pageFetcher =
162+
new PageFetcher<Database, com.google.spanner.admin.database.v1.Database>() {
163+
@Override
164+
public Paginated<com.google.spanner.admin.database.v1.Database> getNextPage(
165+
String nextPageToken) {
166+
return rpc.listDatabases(instanceName, pageSize, nextPageToken);
167+
}
168+
169+
@Override
170+
public Database fromProto(com.google.spanner.admin.database.v1.Database proto) {
171+
return Database.fromProto(proto, DatabaseAdminClientImpl.this);
172+
}
173+
};
174+
if (listOptions.hasPageToken()) {
175+
pageFetcher.setNextPageToken(listOptions.pageToken());
176+
}
177+
return pageFetcher.getNextPage();
178+
}
179+
180+
private String getInstanceName(String instanceId) {
181+
return new InstanceId(projectId, instanceId).getName();
182+
}
183+
184+
private String getDatabaseName(String instanceId, String databaseId) {
185+
return new DatabaseId(new InstanceId(projectId, instanceId), databaseId).getName();
186+
}
187+
}

google-cloud-clients/google-cloud-spanner/src/main/java/com/google/cloud/spanner/SpannerImpl.java

Lines changed: 5 additions & 155 deletions
Original file line numberDiff line numberDiff line change
@@ -57,14 +57,11 @@
5757
import com.google.common.util.concurrent.Uninterruptibles;
5858
import com.google.protobuf.Any;
5959
import com.google.protobuf.ByteString;
60-
import com.google.protobuf.Empty;
6160
import com.google.protobuf.FieldMask;
6261
import com.google.protobuf.InvalidProtocolBufferException;
6362
import com.google.protobuf.ListValue;
6463
import com.google.protobuf.Message;
6564
import com.google.protobuf.Value.KindCase;
66-
import com.google.spanner.admin.database.v1.CreateDatabaseMetadata;
67-
import com.google.spanner.admin.database.v1.UpdateDatabaseDdlMetadata;
6865
import com.google.spanner.admin.instance.v1.CreateInstanceMetadata;
6966
import com.google.spanner.admin.instance.v1.UpdateInstanceMetadata;
7067
import com.google.spanner.v1.BeginTransactionRequest;
@@ -101,7 +98,6 @@
10198
import java.util.List;
10299
import java.util.Map;
103100
import java.util.Random;
104-
import java.util.UUID;
105101
import java.util.concurrent.BlockingQueue;
106102
import java.util.concurrent.Callable;
107103
import java.util.concurrent.CountDownLatch;
@@ -411,7 +407,7 @@ private static <T extends Message> T unpack(Any response, Class<T> clazz)
411407
}
412408
}
413409

414-
private abstract static class PageFetcher<S, T> implements NextPageFetcher<S> {
410+
abstract static class PageFetcher<S, T> implements NextPageFetcher<S> {
415411
private String nextPageToken;
416412

417413
@Override
@@ -432,159 +428,13 @@ public Paginated<T> call() {
432428
return new PageImpl<S>(this, nextPageToken, results);
433429
}
434430

435-
abstract Paginated<T> getNextPage(@Nullable String nextPageToken);
436-
437-
abstract S fromProto(T proto);
438-
}
439-
440-
private static String randomOperationId() {
441-
UUID uuid = UUID.randomUUID();
442-
return ("r" + uuid.toString()).replace("-", "_");
443-
}
444-
445-
static class DatabaseAdminClientImpl implements DatabaseAdminClient {
446-
447-
private final String projectId;
448-
private final SpannerRpc rpc;
449-
450-
DatabaseAdminClientImpl(String projectId, SpannerRpc rpc) {
451-
this.projectId = projectId;
452-
this.rpc = rpc;
431+
void setNextPageToken(String nextPageToken) {
432+
this.nextPageToken = nextPageToken;
453433
}
454434

455-
@Override
456-
public OperationFuture<Database, CreateDatabaseMetadata> createDatabase(
457-
String instanceId, String databaseId, Iterable<String> statements) throws SpannerException {
458-
// CreateDatabase() is not idempotent, so we're not retrying this request.
459-
String instanceName = getInstanceName(instanceId);
460-
String createStatement = "CREATE DATABASE `" + databaseId + "`";
461-
OperationFuture<com.google.spanner.admin.database.v1.Database, CreateDatabaseMetadata>
462-
rawOperationFuture = rpc.createDatabase(instanceName, createStatement, statements);
463-
return new OperationFutureImpl<Database, CreateDatabaseMetadata>(
464-
rawOperationFuture.getPollingFuture(),
465-
rawOperationFuture.getInitialFuture(),
466-
new ApiFunction<OperationSnapshot, Database>() {
467-
@Override
468-
public Database apply(OperationSnapshot snapshot) {
469-
return Database.fromProto(
470-
ProtoOperationTransformers.ResponseTransformer.create(
471-
com.google.spanner.admin.database.v1.Database.class)
472-
.apply(snapshot),
473-
DatabaseAdminClientImpl.this);
474-
}
475-
},
476-
ProtoOperationTransformers.MetadataTransformer.create(CreateDatabaseMetadata.class),
477-
new ApiFunction<Exception, Database>() {
478-
@Override
479-
public Database apply(Exception e) {
480-
throw SpannerExceptionFactory.newSpannerException(e);
481-
}
482-
});
483-
}
484-
485-
@Override
486-
public Database getDatabase(String instanceId, String databaseId) throws SpannerException {
487-
final String dbName = getDatabaseName(instanceId, databaseId);
488-
Callable<Database> callable =
489-
new Callable<Database>() {
490-
@Override
491-
public Database call() throws Exception {
492-
return Database.fromProto(rpc.getDatabase(dbName), DatabaseAdminClientImpl.this);
493-
}
494-
};
495-
return runWithRetries(callable);
496-
}
497-
498-
@Override
499-
public OperationFuture<Void, UpdateDatabaseDdlMetadata> updateDatabaseDdl(
500-
final String instanceId,
501-
final String databaseId,
502-
final Iterable<String> statements,
503-
@Nullable String operationId)
504-
throws SpannerException {
505-
final String dbName = getDatabaseName(instanceId, databaseId);
506-
final String opId = operationId != null ? operationId : randomOperationId();
507-
OperationFuture<Empty, UpdateDatabaseDdlMetadata> rawOperationFuture =
508-
rpc.updateDatabaseDdl(dbName, statements, opId);
509-
return new OperationFutureImpl<Void, UpdateDatabaseDdlMetadata>(
510-
rawOperationFuture.getPollingFuture(),
511-
rawOperationFuture.getInitialFuture(),
512-
new ApiFunction<OperationSnapshot, Void>() {
513-
@Override
514-
public Void apply(OperationSnapshot snapshot) {
515-
ProtoOperationTransformers.ResponseTransformer.create(Empty.class).apply(snapshot);
516-
return null;
517-
}
518-
},
519-
ProtoOperationTransformers.MetadataTransformer.create(UpdateDatabaseDdlMetadata.class),
520-
new ApiFunction<Exception, Void>() {
521-
@Override
522-
public Void apply(Exception e) {
523-
throw SpannerExceptionFactory.newSpannerException(e);
524-
}
525-
});
526-
}
527-
528-
@Override
529-
public void dropDatabase(String instanceId, String databaseId) throws SpannerException {
530-
final String dbName = getDatabaseName(instanceId, databaseId);
531-
Callable<Void> callable =
532-
new Callable<Void>() {
533-
@Override
534-
public Void call() throws Exception {
535-
rpc.dropDatabase(dbName);
536-
return null;
537-
}
538-
};
539-
runWithRetries(callable);
540-
}
541-
542-
@Override
543-
public List<String> getDatabaseDdl(String instanceId, String databaseId) {
544-
final String dbName = getDatabaseName(instanceId, databaseId);
545-
Callable<List<String>> callable =
546-
new Callable<List<String>>() {
547-
@Override
548-
public List<String> call() throws Exception {
549-
return rpc.getDatabaseDdl(dbName);
550-
}
551-
};
552-
return runWithRetries(callable);
553-
}
554-
555-
@Override
556-
public Page<Database> listDatabases(String instanceId, ListOption... options) {
557-
final String instanceName = getInstanceName(instanceId);
558-
final Options listOptions = Options.fromListOptions(options);
559-
Preconditions.checkArgument(
560-
!listOptions.hasFilter(), "Filter option is not support by" + "listDatabases");
561-
final int pageSize = listOptions.hasPageSize() ? listOptions.pageSize() : 0;
562-
PageFetcher<Database, com.google.spanner.admin.database.v1.Database> pageFetcher =
563-
new PageFetcher<Database, com.google.spanner.admin.database.v1.Database>() {
564-
@Override
565-
public Paginated<com.google.spanner.admin.database.v1.Database> getNextPage(
566-
String nextPageToken) {
567-
return rpc.listDatabases(instanceName, pageSize, nextPageToken);
568-
}
569-
570-
@Override
571-
public Database fromProto(com.google.spanner.admin.database.v1.Database proto) {
572-
return Database.fromProto(proto, DatabaseAdminClientImpl.this);
573-
}
574-
};
575-
if (listOptions.hasPageToken()) {
576-
pageFetcher.nextPageToken = listOptions.pageToken();
577-
}
578-
return pageFetcher.getNextPage();
579-
}
580-
581-
private String getInstanceName(String instanceId) {
582-
return new InstanceId(projectId, instanceId).getName();
583-
}
435+
abstract Paginated<T> getNextPage(@Nullable String nextPageToken);
584436

585-
private String getDatabaseName(String instanceId, String databaseId) {
586-
return new DatabaseId(new InstanceId(projectId, instanceId), databaseId).getName();
587-
}
437+
abstract S fromProto(T proto);
588438
}
589439

590440
static class InstanceAdminClientImpl implements InstanceAdminClient {

google-cloud-clients/google-cloud-spanner/src/test/java/com/google/cloud/spanner/DatabaseAdminClientImplTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,12 +52,12 @@ public class DatabaseAdminClientImplTest {
5252
"projects/my-project/instances/my-instance/databases/my-db2";
5353

5454
@Mock SpannerRpc rpc;
55-
SpannerImpl.DatabaseAdminClientImpl client;
55+
DatabaseAdminClientImpl client;
5656

5757
@Before
5858
public void setUp() {
5959
initMocks(this);
60-
client = new SpannerImpl.DatabaseAdminClientImpl(PROJECT_ID, rpc);
60+
client = new DatabaseAdminClientImpl(PROJECT_ID, rpc);
6161
}
6262

6363
private Database getDatabaseProto() {

0 commit comments

Comments
 (0)