Skip to content

Commit a883622

Browse files
authored
docs: add samples for async api (#3429)
* docs: add samples for async api * fix: lint errors * fix: place entire transaction in try block * fix: keep runner in a variable to comply with code example in docs * fix: move both runners to a variable + reformat * docs: add tags
1 parent 4a8b2bf commit a883622

11 files changed

+1295
-1
lines changed

spanner/cloud-client/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ limitations under the License.
4242
<dependency>
4343
<groupId>com.google.cloud</groupId>
4444
<artifactId>libraries-bom</artifactId>
45-
<version>8.0.0</version>
45+
<version>8.1.0</version>
4646
<type>pom</type>
4747
<scope>import</scope>
4848
</dependency>
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/*
2+
* Copyright 2020 Google Inc.
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.example.spanner;
18+
19+
// [START spanner_async_dml_standard_insert]
20+
import com.google.api.core.ApiFuture;
21+
import com.google.cloud.spanner.AsyncRunner;
22+
import com.google.cloud.spanner.AsyncRunner.AsyncWork;
23+
import com.google.cloud.spanner.DatabaseClient;
24+
import com.google.cloud.spanner.DatabaseId;
25+
import com.google.cloud.spanner.Spanner;
26+
import com.google.cloud.spanner.SpannerOptions;
27+
import com.google.cloud.spanner.Statement;
28+
import com.google.cloud.spanner.TransactionContext;
29+
import java.util.concurrent.ExecutionException;
30+
import java.util.concurrent.ExecutorService;
31+
import java.util.concurrent.Executors;
32+
import java.util.concurrent.TimeoutException;
33+
34+
class AsyncDmlExample {
35+
36+
static void asyncDml() throws InterruptedException, ExecutionException, TimeoutException {
37+
// TODO(developer): Replace these variables before running the sample.
38+
String projectId = "my-project";
39+
String instanceId = "my-instance";
40+
String databaseId = "my-database";
41+
42+
try (Spanner spanner =
43+
SpannerOptions.newBuilder().setProjectId(projectId).build().getService()) {
44+
DatabaseClient client =
45+
spanner.getDatabaseClient(DatabaseId.of(projectId, instanceId, databaseId));
46+
asyncDml(client);
47+
}
48+
}
49+
50+
// Execute a DML statement asynchronously.
51+
static void asyncDml(DatabaseClient client)
52+
throws InterruptedException, ExecutionException, TimeoutException {
53+
ExecutorService executor = Executors.newSingleThreadExecutor();
54+
AsyncRunner runner = client.runAsync();
55+
ApiFuture<Long> rowCount =
56+
runner.runAsync(
57+
new AsyncWork<Long>() {
58+
@Override
59+
public ApiFuture<Long> doWorkAsync(TransactionContext txn) {
60+
String sql =
61+
"INSERT INTO Singers (SingerId, FirstName, LastName) VALUES "
62+
+ "(12, 'Melissa', 'Garcia'), "
63+
+ "(13, 'Russell', 'Morales'), "
64+
+ "(14, 'Jacqueline', 'Long'), "
65+
+ "(15, 'Dylan', 'Shaw')";
66+
return txn.executeUpdateAsync(Statement.of(sql));
67+
}
68+
},
69+
executor);
70+
System.out.printf("%d records inserted.%n", rowCount.get());
71+
executor.shutdown();
72+
}
73+
}
74+
//[END spanner_async_dml_standard_insert]
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
/*
2+
* Copyright 2020 Google Inc.
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.example.spanner;
18+
19+
// [START spanner_async_query_data]
20+
import com.google.api.core.ApiFuture;
21+
import com.google.cloud.spanner.AsyncResultSet;
22+
import com.google.cloud.spanner.AsyncResultSet.CallbackResponse;
23+
import com.google.cloud.spanner.AsyncResultSet.ReadyCallback;
24+
import com.google.cloud.spanner.DatabaseClient;
25+
import com.google.cloud.spanner.DatabaseId;
26+
import com.google.cloud.spanner.Spanner;
27+
import com.google.cloud.spanner.SpannerException;
28+
import com.google.cloud.spanner.SpannerOptions;
29+
import com.google.cloud.spanner.Statement;
30+
import java.util.concurrent.ExecutionException;
31+
import java.util.concurrent.ExecutorService;
32+
import java.util.concurrent.Executors;
33+
import java.util.concurrent.TimeUnit;
34+
import java.util.concurrent.TimeoutException;
35+
36+
class AsyncQueryExample {
37+
38+
static void asyncQuery() throws InterruptedException, ExecutionException, TimeoutException {
39+
// TODO(developer): Replace these variables before running the sample.
40+
String projectId = "my-project";
41+
String instanceId = "my-instance";
42+
String databaseId = "my-database";
43+
44+
try (Spanner spanner =
45+
SpannerOptions.newBuilder().setProjectId(projectId).build().getService()) {
46+
DatabaseClient client =
47+
spanner.getDatabaseClient(DatabaseId.of(projectId, instanceId, databaseId));
48+
asyncQuery(client);
49+
}
50+
}
51+
52+
// Execute a query asynchronously and process the results in a callback.
53+
static void asyncQuery(DatabaseClient client)
54+
throws InterruptedException, ExecutionException, TimeoutException {
55+
ApiFuture<Void> finished;
56+
ExecutorService executor = Executors.newSingleThreadExecutor();
57+
try (AsyncResultSet resultSet =
58+
client
59+
.singleUse()
60+
.executeQueryAsync(Statement.of("SELECT SingerId, AlbumId, AlbumTitle FROM Albums"))) {
61+
// Setting a callback will automatically start the iteration over the results of the query
62+
// using the specified executor. The callback will be called at least once. The returned
63+
// ApiFuture is done when the callback has returned DONE and all resources used by the
64+
// AsyncResultSet have been released.
65+
finished =
66+
resultSet.setCallback(
67+
executor,
68+
new ReadyCallback() {
69+
@Override
70+
public CallbackResponse cursorReady(AsyncResultSet resultSet) {
71+
try {
72+
while (true) {
73+
switch (resultSet.tryNext()) {
74+
// OK: There is a row ready.
75+
case OK:
76+
System.out.printf(
77+
"%d %d %s%n",
78+
resultSet.getLong(0), resultSet.getLong(1), resultSet.getString(2));
79+
break;
80+
81+
// DONE: There are no more rows in the result set.
82+
case DONE:
83+
return CallbackResponse.DONE;
84+
85+
// NOT_READY: There are currently no more rows in the buffer.
86+
case NOT_READY:
87+
return CallbackResponse.CONTINUE;
88+
89+
default:
90+
throw new IllegalStateException();
91+
}
92+
}
93+
} catch (SpannerException e) {
94+
System.out.printf("Error in callback: %s%n", e.getMessage());
95+
return CallbackResponse.DONE;
96+
}
97+
}
98+
});
99+
}
100+
101+
// This ApiFuture is done when the callback has returned DONE and all resources of the
102+
// asynchronous result set have been released.
103+
finished.get(30L, TimeUnit.SECONDS);
104+
executor.shutdown();
105+
}
106+
}
107+
//[END spanner_async_query_data]
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
/*
2+
* Copyright 2020 Google Inc.
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.example.spanner;
18+
19+
// [START spanner_async_query_to_list]
20+
import com.google.api.core.ApiFuture;
21+
import com.google.cloud.spanner.AsyncResultSet;
22+
import com.google.cloud.spanner.DatabaseClient;
23+
import com.google.cloud.spanner.DatabaseId;
24+
import com.google.cloud.spanner.Spanner;
25+
import com.google.cloud.spanner.SpannerOptions;
26+
import com.google.cloud.spanner.Statement;
27+
import com.google.common.collect.ImmutableList;
28+
import java.util.concurrent.ExecutionException;
29+
import java.util.concurrent.ExecutorService;
30+
import java.util.concurrent.Executors;
31+
import java.util.concurrent.TimeUnit;
32+
import java.util.concurrent.TimeoutException;
33+
34+
class AsyncQueryToListAsyncExample {
35+
static class Album {
36+
final long singerId;
37+
final long albumId;
38+
final String albumTitle;
39+
40+
Album(long singerId, long albumId, String albumTitle) {
41+
this.singerId = singerId;
42+
this.albumId = albumId;
43+
this.albumTitle = albumTitle;
44+
}
45+
}
46+
47+
static void asyncQueryToList() throws InterruptedException, ExecutionException, TimeoutException {
48+
// TODO(developer): Replace these variables before running the sample.
49+
String projectId = "my-project";
50+
String instanceId = "my-instance";
51+
String databaseId = "my-database";
52+
53+
try (Spanner spanner =
54+
SpannerOptions.newBuilder().setProjectId(projectId).build().getService()) {
55+
DatabaseClient client =
56+
spanner.getDatabaseClient(DatabaseId.of(projectId, instanceId, databaseId));
57+
asyncQueryToList(client);
58+
}
59+
}
60+
61+
// Execute a query asynchronously and transform the result to a list.
62+
static void asyncQueryToList(DatabaseClient client)
63+
throws InterruptedException, ExecutionException, TimeoutException {
64+
ExecutorService executor = Executors.newSingleThreadExecutor();
65+
ApiFuture<ImmutableList<Album>> albums;
66+
try (AsyncResultSet resultSet =
67+
client
68+
.singleUse()
69+
.executeQueryAsync(Statement.of("SELECT SingerId, AlbumId, AlbumTitle FROM Albums"))) {
70+
// Convert the result set to a list of Albums asynchronously.
71+
albums =
72+
resultSet.toListAsync(
73+
reader -> {
74+
return new Album(
75+
reader.getLong("SingerId"),
76+
reader.getLong("AlbumId"),
77+
reader.getString("AlbumTitle"));
78+
},
79+
executor);
80+
}
81+
82+
for (Album album : albums.get(30L, TimeUnit.SECONDS)) {
83+
System.out.printf("%d %d %s%n", album.singerId, album.albumId, album.albumTitle);
84+
}
85+
executor.shutdown();
86+
}
87+
}
88+
//[END spanner_async_query_to_list]
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
/*
2+
* Copyright 2020 Google Inc.
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.example.spanner;
18+
19+
// [START spanner_async_read_data]
20+
import com.google.api.core.ApiFuture;
21+
import com.google.cloud.spanner.AsyncResultSet;
22+
import com.google.cloud.spanner.AsyncResultSet.CallbackResponse;
23+
import com.google.cloud.spanner.AsyncResultSet.ReadyCallback;
24+
import com.google.cloud.spanner.DatabaseClient;
25+
import com.google.cloud.spanner.DatabaseId;
26+
import com.google.cloud.spanner.KeySet;
27+
import com.google.cloud.spanner.Spanner;
28+
import com.google.cloud.spanner.SpannerException;
29+
import com.google.cloud.spanner.SpannerOptions;
30+
import java.util.Arrays;
31+
import java.util.concurrent.ExecutionException;
32+
import java.util.concurrent.ExecutorService;
33+
import java.util.concurrent.Executors;
34+
import java.util.concurrent.TimeUnit;
35+
import java.util.concurrent.TimeoutException;
36+
37+
class AsyncReadExample {
38+
39+
static void asyncRead() throws InterruptedException, ExecutionException, TimeoutException {
40+
// TODO(developer): Replace these variables before running the sample.
41+
String projectId = "my-project";
42+
String instanceId = "my-instance";
43+
String databaseId = "my-database";
44+
45+
try (Spanner spanner =
46+
SpannerOptions.newBuilder().setProjectId(projectId).build().getService()) {
47+
DatabaseClient client =
48+
spanner.getDatabaseClient(DatabaseId.of(projectId, instanceId, databaseId));
49+
asyncRead(client);
50+
}
51+
}
52+
53+
// Execute a query asynchronously and process the results in a callback.
54+
static void asyncRead(DatabaseClient client)
55+
throws InterruptedException, ExecutionException, TimeoutException {
56+
ApiFuture<Void> finished;
57+
ExecutorService executor = Executors.newSingleThreadExecutor();
58+
try (AsyncResultSet resultSet =
59+
client
60+
.singleUse()
61+
.readAsync(
62+
"Albums",
63+
KeySet.all(), // Read all rows in a table.
64+
Arrays.asList("SingerId", "AlbumId", "AlbumTitle"))) {
65+
// Setting a callback will automatically start the iteration over the results of the query
66+
// using the specified executor. The callback will be called at least once. The returned
67+
// ApiFuture is done when the callback has returned DONE and all resources used by the
68+
// AsyncResultSet have been released.
69+
finished =
70+
resultSet.setCallback(
71+
executor,
72+
new ReadyCallback() {
73+
@Override
74+
public CallbackResponse cursorReady(AsyncResultSet resultSet) {
75+
try {
76+
while (true) {
77+
switch (resultSet.tryNext()) {
78+
// OK: There is a row ready.
79+
case OK:
80+
System.out.printf(
81+
"%d %d %s%n",
82+
resultSet.getLong(0), resultSet.getLong(1), resultSet.getString(2));
83+
break;
84+
85+
// DONE: There are no more rows in the result set.
86+
case DONE:
87+
return CallbackResponse.DONE;
88+
89+
// NOT_READY: There are currently no more rows in the buffer.
90+
case NOT_READY:
91+
return CallbackResponse.CONTINUE;
92+
93+
default:
94+
throw new IllegalStateException();
95+
}
96+
}
97+
} catch (SpannerException e) {
98+
System.out.printf("Error in callback: %s%n", e.getMessage());
99+
return CallbackResponse.DONE;
100+
}
101+
}
102+
});
103+
}
104+
105+
// This ApiFuture is done when the callback has returned DONE and all resources of the
106+
// asynchronous result set have been released.
107+
finished.get(30L, TimeUnit.SECONDS);
108+
executor.shutdown();
109+
}
110+
}
111+
//[END spanner_async_read_data]

0 commit comments

Comments
 (0)