From a5f7ceb9c190b75ddb08c42873174c3111a13c3a Mon Sep 17 00:00:00 2001 From: Shuran Zhang Date: Mon, 13 Jan 2025 21:37:28 +0000 Subject: [PATCH 1/3] docs(samples): add samples and tests for change streams txn exclusion --- .../ChangeStreamsTxnExclusionSample.java | 68 +++++++++++++ .../ChangeStreamsTxnExclusionSampleIT.java | 97 +++++++++++++++++++ 2 files changed, 165 insertions(+) create mode 100644 samples/snippets/src/main/java/com/example/spanner/ChangeStreamsTxnExclusionSample.java create mode 100644 samples/snippets/src/test/java/com/example/spanner/ChangeStreamsTxnExclusionSampleIT.java diff --git a/samples/snippets/src/main/java/com/example/spanner/ChangeStreamsTxnExclusionSample.java b/samples/snippets/src/main/java/com/example/spanner/ChangeStreamsTxnExclusionSample.java new file mode 100644 index 00000000000..78a53aaa5f7 --- /dev/null +++ b/samples/snippets/src/main/java/com/example/spanner/ChangeStreamsTxnExclusionSample.java @@ -0,0 +1,68 @@ +/* + * Copyright 2021 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.example.spanner; + +import com.google.cloud.spanner.DatabaseClient; +import com.google.cloud.spanner.DatabaseId; +import com.google.cloud.spanner.Options; +import com.google.cloud.spanner.Spanner; +import com.google.cloud.spanner.SpannerOptions; +import com.google.cloud.spanner.Statement; + +/** + * Sample showing how to set exclude transaction from change streams in different write requests. + */ +public class ChangeStreamsTxnExclusionSample { + + static void setExcludeTxnFromChangeStreams() { + // TODO(developer): Replace these variables before running the sample. + final String projectId = "my-instance"; + final String instanceId = "my-project"; + final String databaseId = "my-database"; + + try (Spanner spanner = + SpannerOptions.newBuilder().setProjectId(projectId).build().getService()) { + final DatabaseClient databaseClient = + spanner.getDatabaseClient(DatabaseId.of(projectId, instanceId, databaseId)); + rwTxnExcludedFromChangeStreams(databaseClient); + } + } + + // [START spanner_set_exclude_txn_from_change_streams] + static void rwTxnExcludedFromChangeStreams(DatabaseClient client) { + // Exclude the transaction from allowed tracking change streams with alloww_txn_exclusion=true. + // This exclusion will be applied to all the individual operations inside this transaction. + client + .readWriteTransaction(Options.excludeTxnFromChangeStreams()) + .run( + transaction -> { + transaction.executeUpdate( + Statement.of( + "INSERT Singers (SingerId, FirstName, LastName)\n" + + "VALUES (1341, 'Virginia', 'Watson')")); + System.out.println("New singer inserted."); + + transaction.executeUpdate( + Statement.of("UPDATE Singers SET FirstName = 'Hi' WHERE SingerId = 111")); + System.out.println("Singer first name updated."); + + return null; + }); + } + // [END spanner_set_exclude_txn_from_change_streams] + +} diff --git a/samples/snippets/src/test/java/com/example/spanner/ChangeStreamsTxnExclusionSampleIT.java b/samples/snippets/src/test/java/com/example/spanner/ChangeStreamsTxnExclusionSampleIT.java new file mode 100644 index 00000000000..bec42654229 --- /dev/null +++ b/samples/snippets/src/test/java/com/example/spanner/ChangeStreamsTxnExclusionSampleIT.java @@ -0,0 +1,97 @@ +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.example.spanner; + +import static com.example.spanner.SampleRunner.runSample; +import static com.google.common.truth.Truth.assertThat; + +import com.google.cloud.spanner.DatabaseClient; +import com.google.cloud.spanner.DatabaseId; +import com.google.cloud.spanner.KeySet; +import com.google.cloud.spanner.Mutation; +import com.google.common.collect.ImmutableList; +import java.util.Arrays; +import java.util.Collections; +import org.junit.After; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Integration tests for {@link ChangeStreamsTxnExclusionSample} */ +@RunWith(JUnit4.class) +public class ChangeStreamsTxnExclusionSampleIT extends SampleTestBase { + + private static DatabaseId databaseId; + + @BeforeClass + public static void createTestDatabase() throws Exception { + final String database = idGenerator.generateDatabaseId(); + databaseAdminClient + .createDatabase( + instanceId, + database, + ImmutableList.of( + "CREATE TABLE Singers (" + + " SingerId INT64 NOT NULL," + + " FirstName STRING(1024)," + + " LastName STRING(1024)," + + " SingerInfo BYTES(MAX)" + + ") PRIMARY KEY (SingerId)")) + .get(); + databaseId = DatabaseId.of(projectId, instanceId, database); + } + + @Before + public void insertTestData() { + final DatabaseClient client = spanner.getDatabaseClient(databaseId); + client.write( + Arrays.asList( + Mutation.newInsertBuilder("Singers") + .set("SingerId") + .to(1L) + .set("FirstName") + .to("first name 1") + .set("LastName") + .to("last name 1") + .build(), + Mutation.newInsertBuilder("Singers") + .set("SingerId") + .to(2L) + .set("FirstName") + .to("first name 2") + .set("LastName") + .to("last name 2") + .build())); + } + + @After + public void removeTestData() { + final DatabaseClient client = spanner.getDatabaseClient(databaseId); + client.write(Collections.singletonList(Mutation.delete("Singers", KeySet.all()))); + } + + @Test + public void testSetExcludeTxnFromChangeStreamsSampleSample() throws Exception { + final DatabaseClient client = spanner.getDatabaseClient(databaseId); + String out = + runSample(() -> ChangeStreamsTxnExclusionSample.rwTxnExcludedFromChangeStreams(client)); + assertThat(out).contains("New singer inserted."); + assertThat(out).contains("Singer first name updated."); + } +} From 57d3ad56e1c152a16ab818b465d9ea64b2964900 Mon Sep 17 00:00:00 2001 From: Shuran Zhang Date: Tue, 21 Jan 2025 23:57:47 +0000 Subject: [PATCH 2/3] Rename rwTxn to readWriteTxn --- .../com/example/spanner/ChangeStreamsTxnExclusionSample.java | 4 ++-- .../example/spanner/ChangeStreamsTxnExclusionSampleIT.java | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/samples/snippets/src/main/java/com/example/spanner/ChangeStreamsTxnExclusionSample.java b/samples/snippets/src/main/java/com/example/spanner/ChangeStreamsTxnExclusionSample.java index 78a53aaa5f7..4b68d14018c 100644 --- a/samples/snippets/src/main/java/com/example/spanner/ChangeStreamsTxnExclusionSample.java +++ b/samples/snippets/src/main/java/com/example/spanner/ChangeStreamsTxnExclusionSample.java @@ -38,12 +38,12 @@ static void setExcludeTxnFromChangeStreams() { SpannerOptions.newBuilder().setProjectId(projectId).build().getService()) { final DatabaseClient databaseClient = spanner.getDatabaseClient(DatabaseId.of(projectId, instanceId, databaseId)); - rwTxnExcludedFromChangeStreams(databaseClient); + readWriteTxnExcludedFromChangeStreams(databaseClient); } } // [START spanner_set_exclude_txn_from_change_streams] - static void rwTxnExcludedFromChangeStreams(DatabaseClient client) { + static void readWriteTxnExcludedFromChangeStreams(DatabaseClient client) { // Exclude the transaction from allowed tracking change streams with alloww_txn_exclusion=true. // This exclusion will be applied to all the individual operations inside this transaction. client diff --git a/samples/snippets/src/test/java/com/example/spanner/ChangeStreamsTxnExclusionSampleIT.java b/samples/snippets/src/test/java/com/example/spanner/ChangeStreamsTxnExclusionSampleIT.java index bec42654229..6058b1872a1 100644 --- a/samples/snippets/src/test/java/com/example/spanner/ChangeStreamsTxnExclusionSampleIT.java +++ b/samples/snippets/src/test/java/com/example/spanner/ChangeStreamsTxnExclusionSampleIT.java @@ -90,7 +90,8 @@ public void removeTestData() { public void testSetExcludeTxnFromChangeStreamsSampleSample() throws Exception { final DatabaseClient client = spanner.getDatabaseClient(databaseId); String out = - runSample(() -> ChangeStreamsTxnExclusionSample.rwTxnExcludedFromChangeStreams(client)); + runSample( + () -> ChangeStreamsTxnExclusionSample.readWriteTxnExcludedFromChangeStreams(client)); assertThat(out).contains("New singer inserted."); assertThat(out).contains("Singer first name updated."); } From 98aae9b4424780dc2b7c929870e2a52162875449 Mon Sep 17 00:00:00 2001 From: Shuran Zhang Date: Tue, 28 Jan 2025 18:03:44 +0000 Subject: [PATCH 3/3] Fix copyright year --- .../com/example/spanner/ChangeStreamsTxnExclusionSample.java | 2 +- .../com/example/spanner/ChangeStreamsTxnExclusionSampleIT.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/samples/snippets/src/main/java/com/example/spanner/ChangeStreamsTxnExclusionSample.java b/samples/snippets/src/main/java/com/example/spanner/ChangeStreamsTxnExclusionSample.java index 4b68d14018c..10a7c4b26d4 100644 --- a/samples/snippets/src/main/java/com/example/spanner/ChangeStreamsTxnExclusionSample.java +++ b/samples/snippets/src/main/java/com/example/spanner/ChangeStreamsTxnExclusionSample.java @@ -1,5 +1,5 @@ /* - * Copyright 2021 Google LLC + * Copyright 2025 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/samples/snippets/src/test/java/com/example/spanner/ChangeStreamsTxnExclusionSampleIT.java b/samples/snippets/src/test/java/com/example/spanner/ChangeStreamsTxnExclusionSampleIT.java index 6058b1872a1..fecf8189f46 100644 --- a/samples/snippets/src/test/java/com/example/spanner/ChangeStreamsTxnExclusionSampleIT.java +++ b/samples/snippets/src/test/java/com/example/spanner/ChangeStreamsTxnExclusionSampleIT.java @@ -1,5 +1,5 @@ /* - * Copyright 2024 Google LLC + * Copyright 2025 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License.