From 28217fda00893af68a0792a75f073e9b4e971533 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Wed, 10 May 2023 14:56:13 +0000 Subject: [PATCH 01/14] chore(main): release 2.14.7-SNAPSHOT (#1072) :robot: I have created a release *beep* *boop* --- ### Updating meta-information for bleeding-edge SNAPSHOT release. --- This PR was generated with [Release Please](https://togithub.com/googleapis/release-please). See [documentation](https://togithub.com/googleapis/release-please#release-please). --- datastore-v1-proto-client/pom.xml | 4 ++-- google-cloud-datastore-bom/pom.xml | 10 +++++----- google-cloud-datastore/pom.xml | 4 ++-- grpc-google-cloud-datastore-admin-v1/pom.xml | 4 ++-- pom.xml | 12 ++++++------ proto-google-cloud-datastore-admin-v1/pom.xml | 4 ++-- proto-google-cloud-datastore-v1/pom.xml | 4 ++-- versions.txt | 12 ++++++------ 8 files changed, 27 insertions(+), 27 deletions(-) diff --git a/datastore-v1-proto-client/pom.xml b/datastore-v1-proto-client/pom.xml index 79b0d7499..e2bcefbc2 100644 --- a/datastore-v1-proto-client/pom.xml +++ b/datastore-v1-proto-client/pom.xml @@ -19,12 +19,12 @@ 4.0.0 com.google.cloud.datastore datastore-v1-proto-client - 2.14.6 + 2.14.7-SNAPSHOT com.google.cloud google-cloud-datastore-parent - 2.14.6 + 2.14.7-SNAPSHOT jar diff --git a/google-cloud-datastore-bom/pom.xml b/google-cloud-datastore-bom/pom.xml index 59c6e3d68..6dae71644 100644 --- a/google-cloud-datastore-bom/pom.xml +++ b/google-cloud-datastore-bom/pom.xml @@ -3,7 +3,7 @@ 4.0.0 com.google.cloud google-cloud-datastore-bom - 2.14.6 + 2.14.7-SNAPSHOT pom com.google.cloud @@ -52,22 +52,22 @@ com.google.cloud google-cloud-datastore - 2.14.6 + 2.14.7-SNAPSHOT com.google.api.grpc grpc-google-cloud-datastore-admin-v1 - 2.14.6 + 2.14.7-SNAPSHOT com.google.api.grpc proto-google-cloud-datastore-v1 - 0.105.6 + 0.105.7-SNAPSHOT com.google.api.grpc proto-google-cloud-datastore-admin-v1 - 2.14.6 + 2.14.7-SNAPSHOT diff --git a/google-cloud-datastore/pom.xml b/google-cloud-datastore/pom.xml index 4b90a148c..c56273e38 100644 --- a/google-cloud-datastore/pom.xml +++ b/google-cloud-datastore/pom.xml @@ -2,7 +2,7 @@ 4.0.0 google-cloud-datastore - 2.14.6 + 2.14.7-SNAPSHOT jar Google Cloud Datastore https://github.com/googleapis/java-datastore @@ -12,7 +12,7 @@ com.google.cloud google-cloud-datastore-parent - 2.14.6 + 2.14.7-SNAPSHOT google-cloud-datastore diff --git a/grpc-google-cloud-datastore-admin-v1/pom.xml b/grpc-google-cloud-datastore-admin-v1/pom.xml index 04c30c10b..268b3ab78 100644 --- a/grpc-google-cloud-datastore-admin-v1/pom.xml +++ b/grpc-google-cloud-datastore-admin-v1/pom.xml @@ -4,13 +4,13 @@ 4.0.0 com.google.api.grpc grpc-google-cloud-datastore-admin-v1 - 2.14.6 + 2.14.7-SNAPSHOT grpc-google-cloud-datastore-admin-v1 GRPC library for google-cloud-datastore com.google.cloud google-cloud-datastore-parent - 2.14.6 + 2.14.7-SNAPSHOT diff --git a/pom.xml b/pom.xml index 3c0825dca..80c391ec0 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ com.google.cloud google-cloud-datastore-parent pom - 2.14.6 + 2.14.7-SNAPSHOT Google Cloud Datastore Parent https://github.com/googleapis/java-datastore @@ -159,27 +159,27 @@ com.google.api.grpc proto-google-cloud-datastore-admin-v1 - 2.14.6 + 2.14.7-SNAPSHOT com.google.api.grpc grpc-google-cloud-datastore-admin-v1 - 2.14.6 + 2.14.7-SNAPSHOT com.google.cloud google-cloud-datastore - 2.14.6 + 2.14.7-SNAPSHOT com.google.api.grpc proto-google-cloud-datastore-v1 - 0.105.6 + 0.105.7-SNAPSHOT com.google.cloud.datastore datastore-v1-proto-client - 2.14.6 + 2.14.7-SNAPSHOT com.google.api.grpc diff --git a/proto-google-cloud-datastore-admin-v1/pom.xml b/proto-google-cloud-datastore-admin-v1/pom.xml index ef5aacc99..5c1b10653 100644 --- a/proto-google-cloud-datastore-admin-v1/pom.xml +++ b/proto-google-cloud-datastore-admin-v1/pom.xml @@ -4,13 +4,13 @@ 4.0.0 com.google.api.grpc proto-google-cloud-datastore-admin-v1 - 2.14.6 + 2.14.7-SNAPSHOT proto-google-cloud-datastore-admin-v1 Proto library for google-cloud-datastore com.google.cloud google-cloud-datastore-parent - 2.14.6 + 2.14.7-SNAPSHOT diff --git a/proto-google-cloud-datastore-v1/pom.xml b/proto-google-cloud-datastore-v1/pom.xml index e4f046394..336513bb7 100644 --- a/proto-google-cloud-datastore-v1/pom.xml +++ b/proto-google-cloud-datastore-v1/pom.xml @@ -4,13 +4,13 @@ 4.0.0 com.google.api.grpc proto-google-cloud-datastore-v1 - 0.105.6 + 0.105.7-SNAPSHOT proto-google-cloud-datastore-v1 PROTO library for proto-google-cloud-datastore-v1 com.google.cloud google-cloud-datastore-parent - 2.14.6 + 2.14.7-SNAPSHOT diff --git a/versions.txt b/versions.txt index 063513c96..7614b37a6 100644 --- a/versions.txt +++ b/versions.txt @@ -1,9 +1,9 @@ # Format: # module:released-version:current-version -google-cloud-datastore:2.14.6:2.14.6 -google-cloud-datastore-bom:2.14.6:2.14.6 -proto-google-cloud-datastore-v1:0.105.6:0.105.6 -datastore-v1-proto-client:2.14.6:2.14.6 -proto-google-cloud-datastore-admin-v1:2.14.6:2.14.6 -grpc-google-cloud-datastore-admin-v1:2.14.6:2.14.6 +google-cloud-datastore:2.14.6:2.14.7-SNAPSHOT +google-cloud-datastore-bom:2.14.6:2.14.7-SNAPSHOT +proto-google-cloud-datastore-v1:0.105.6:0.105.7-SNAPSHOT +datastore-v1-proto-client:2.14.6:2.14.7-SNAPSHOT +proto-google-cloud-datastore-admin-v1:2.14.6:2.14.7-SNAPSHOT +grpc-google-cloud-datastore-admin-v1:2.14.6:2.14.7-SNAPSHOT From 239001682bd1284be39d4646ce0594274070c143 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 11 May 2023 16:06:13 +0200 Subject: [PATCH 02/14] deps: update dependency com.google.errorprone:error_prone_core to v2.19.1 (#1069) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [com.google.errorprone:error_prone_core](https://errorprone.info) ([source](https://togithub.com/google/error-prone)) | `2.18.0` -> `2.19.1` | [![age](https://badges.renovateapi.com/packages/maven/com.google.errorprone:error_prone_core/2.19.1/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.errorprone:error_prone_core/2.19.1/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.errorprone:error_prone_core/2.19.1/compatibility-slim/2.18.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.errorprone:error_prone_core/2.19.1/confidence-slim/2.18.0)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
google/error-prone ### [`v2.19.1`](https://togithub.com/google/error-prone/releases/tag/v2.19.1): Error Prone 2.19.1 This release fixes a binary compatibility issue when running on JDK 11, see [#​3895](https://togithub.com/google/error-prone/issues/3895) **Full Changelog**: https://togithub.com/google/error-prone/compare/v2.19.0...v2.19.1 ### [`v2.19.0`](https://togithub.com/google/error-prone/releases/tag/v2.19.0): Error Prone 2.19.0 New Checkers: - [`NotJavadoc`](https://errorprone.info/bugpattern/NotJavadoc) - [`StringCaseLocaleUsage`](https://errorprone.info/bugpattern/StringCaseLocaleUsage) - [`UnnecessaryTestMethodPrefix`](https://errorprone.info/bugpattern/UnnecessaryTestMethodPrefix) Fixes issues: [#​956](https://togithub.com/google/error-prone/issues/956), [#​3504](https://togithub.com/google/error-prone/issues/3504), [#​3654](https://togithub.com/google/error-prone/issues/3654), [#​3703](https://togithub.com/google/error-prone/issues/3703), [#​3731](https://togithub.com/google/error-prone/issues/3731), [#​3737](https://togithub.com/google/error-prone/issues/3737), [#​3760](https://togithub.com/google/error-prone/issues/3760), [#​3779](https://togithub.com/google/error-prone/issues/3779), [#​3796](https://togithub.com/google/error-prone/issues/3796), [#​3809](https://togithub.com/google/error-prone/issues/3809), [#​3813](https://togithub.com/google/error-prone/issues/3813) **Full Changelog**: https://togithub.com/google/error-prone/compare/v2.18.0...v2.19.0
--- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-datastore). --- README.md | 6 +++--- pom.xml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index dc40e92f8..1e3c8bc1e 100644 --- a/README.md +++ b/README.md @@ -57,13 +57,13 @@ implementation 'com.google.cloud:google-cloud-datastore' If you are using Gradle without BOM, add this to your dependencies: ```Groovy -implementation 'com.google.cloud:google-cloud-datastore:2.14.5' +implementation 'com.google.cloud:google-cloud-datastore:2.14.6' ``` If you are using SBT, add this to your dependencies: ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-datastore" % "2.14.5" +libraryDependencies += "com.google.cloud" % "google-cloud-datastore" % "2.14.6" ``` @@ -370,7 +370,7 @@ Java is a registered trademark of Oracle and/or its affiliates. [kokoro-badge-link-5]: http://storage.googleapis.com/cloud-devrel-public/java/badges/java-datastore/java11.html [stability-image]: https://img.shields.io/badge/stability-stable-green [maven-version-image]: https://img.shields.io/maven-central/v/com.google.cloud/google-cloud-datastore.svg -[maven-version-link]: https://central.sonatype.com/artifact/com.google.cloud/google-cloud-datastore/2.14.5 +[maven-version-link]: https://central.sonatype.com/artifact/com.google.cloud/google-cloud-datastore/2.14.6 [authentication]: https://github.com/googleapis/google-cloud-java#authentication [auth-scopes]: https://developers.google.com/identity/protocols/oauth2/scopes [predefined-iam-roles]: https://cloud.google.com/iam/docs/understanding-roles#predefined_roles diff --git a/pom.xml b/pom.xml index 80c391ec0..71b78eec7 100644 --- a/pom.xml +++ b/pom.xml @@ -143,7 +143,7 @@ github google-cloud-datastore-parent https://googleapis.dev/java/google-api-grpc/latest - 2.18.0 + 2.19.1
From a4db89502e9611bf5f9760bfceb1025cc99a9830 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 11 May 2023 16:29:22 +0200 Subject: [PATCH 03/14] deps: update dependency org.graalvm.buildtools:native-maven-plugin to v0.9.22 (#1075) --- samples/native-image-sample/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/native-image-sample/pom.xml b/samples/native-image-sample/pom.xml index e865b2bb5..90fddce85 100644 --- a/samples/native-image-sample/pom.xml +++ b/samples/native-image-sample/pom.xml @@ -107,7 +107,7 @@ org.graalvm.buildtools native-maven-plugin - 0.9.21 + 0.9.22 true com.example.datastore.NativeImageDatastoreSample From c0cc4565cc0e34098f5bc97c031ae671af44fcf3 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 11 May 2023 16:29:36 +0200 Subject: [PATCH 04/14] deps: update dependency org.graalvm.buildtools:junit-platform-native to v0.9.22 (#1074) --- samples/native-image-sample/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/native-image-sample/pom.xml b/samples/native-image-sample/pom.xml index 90fddce85..b03cced94 100644 --- a/samples/native-image-sample/pom.xml +++ b/samples/native-image-sample/pom.xml @@ -86,7 +86,7 @@ org.graalvm.buildtools junit-platform-native - 0.9.21 + 0.9.22 test From 1dab7646f7c381f0239f12dffd29f7782d54a689 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 11 May 2023 16:29:50 +0200 Subject: [PATCH 05/14] chore(deps): update dependency com.google.cloud:google-cloud-datastore to v2.14.6 (#1073) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore(deps): update dependency com.google.cloud:google-cloud-datastore to v2.14.6 * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md --------- Co-authored-by: Owl Bot --- README.md | 2 +- samples/install-without-bom/pom.xml | 2 +- samples/snapshot/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 1e3c8bc1e..77ab9010b 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,7 @@ If you are using Maven without the BOM, add this to your dependencies: com.google.cloud google-cloud-datastore - 2.14.5 + 2.14.6 ``` diff --git a/samples/install-without-bom/pom.xml b/samples/install-without-bom/pom.xml index c5147926b..a55e19cd0 100644 --- a/samples/install-without-bom/pom.xml +++ b/samples/install-without-bom/pom.xml @@ -29,7 +29,7 @@ com.google.cloud google-cloud-datastore - 2.14.5 + 2.14.6 diff --git a/samples/snapshot/pom.xml b/samples/snapshot/pom.xml index a71ad69ab..b10c3629d 100644 --- a/samples/snapshot/pom.xml +++ b/samples/snapshot/pom.xml @@ -28,7 +28,7 @@ com.google.cloud google-cloud-datastore - 2.14.5 + 2.14.6 From 79c7b241002025d4c1338806948ef54874881237 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Fri, 12 May 2023 11:54:37 +0200 Subject: [PATCH 06/14] build(deps): update dependency org.codehaus.mojo:build-helper-maven-plugin to v3.4.0 (#1077) --- samples/install-without-bom/pom.xml | 2 +- samples/snapshot/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/samples/install-without-bom/pom.xml b/samples/install-without-bom/pom.xml index a55e19cd0..5a68aec6a 100644 --- a/samples/install-without-bom/pom.xml +++ b/samples/install-without-bom/pom.xml @@ -53,7 +53,7 @@ org.codehaus.mojo build-helper-maven-plugin - 3.3.0 + 3.4.0 add-snippets-source diff --git a/samples/snapshot/pom.xml b/samples/snapshot/pom.xml index b10c3629d..6421d6f95 100644 --- a/samples/snapshot/pom.xml +++ b/samples/snapshot/pom.xml @@ -52,7 +52,7 @@ org.codehaus.mojo build-helper-maven-plugin - 3.3.0 + 3.4.0 add-snippets-source From 2fca5c80857118ffc22c5b247c51b2fc9cd70653 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Wed, 17 May 2023 10:36:35 +0200 Subject: [PATCH 07/14] chore(deps): update dependency com.google.cloud:libraries-bom to v26.15.0 (#1078) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore(deps): update dependency com.google.cloud:libraries-bom to v26.15.0 * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md --------- Co-authored-by: Owl Bot --- README.md | 4 ++-- samples/native-image-sample/pom.xml | 2 +- samples/snippets/pom.xml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 77ab9010b..b05e0716c 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ If you are using Maven with [BOM][libraries-bom], add this to your pom.xml file: com.google.cloud libraries-bom - 26.14.0 + 26.15.0 pom import @@ -50,7 +50,7 @@ If you are using Maven without the BOM, add this to your dependencies: If you are using Gradle 5.x or later, add this to your dependencies: ```Groovy -implementation platform('com.google.cloud:libraries-bom:26.14.0') +implementation platform('com.google.cloud:libraries-bom:26.15.0') implementation 'com.google.cloud:google-cloud-datastore' ``` diff --git a/samples/native-image-sample/pom.xml b/samples/native-image-sample/pom.xml index b03cced94..4db871c2b 100644 --- a/samples/native-image-sample/pom.xml +++ b/samples/native-image-sample/pom.xml @@ -28,7 +28,7 @@ com.google.cloud libraries-bom - 26.14.0 + 26.15.0 pom import diff --git a/samples/snippets/pom.xml b/samples/snippets/pom.xml index 315ff268a..cde13ac88 100644 --- a/samples/snippets/pom.xml +++ b/samples/snippets/pom.xml @@ -30,7 +30,7 @@ com.google.cloud libraries-bom - 26.14.0 + 26.15.0 pom import From 6f03fab493bca84638a322ab8c72e5cda57c07dc Mon Sep 17 00:00:00 2001 From: Prateek Date: Fri, 19 May 2023 11:22:12 +0530 Subject: [PATCH 08/14] test(fix): testing the serializability behaviour without relying on the underlying concurrency (#1079) fix #497 Since we are testing the behaviour _(i.e. if two transactions conflict with each other, the database guarantees that only one can commit successfully at a time)_ now, both of the tests are now agnostic of underlying concurrency mechanism. This makes sure that both of the tests continue to pass in any gcloud project . --- .../cloud/datastore/it/ITDatastoreTest.java | 102 +++++++++++------- .../cloud/datastore/it/StatementExecutor.java | 91 ++++++++++++++++ 2 files changed, 155 insertions(+), 38 deletions(-) create mode 100644 google-cloud-datastore/src/test/java/com/google/cloud/datastore/it/StatementExecutor.java diff --git a/google-cloud-datastore/src/test/java/com/google/cloud/datastore/it/ITDatastoreTest.java b/google-cloud-datastore/src/test/java/com/google/cloud/datastore/it/ITDatastoreTest.java index f010d8135..3a5ccabac 100644 --- a/google-cloud-datastore/src/test/java/com/google/cloud/datastore/it/ITDatastoreTest.java +++ b/google-cloud-datastore/src/test/java/com/google/cloud/datastore/it/ITDatastoreTest.java @@ -29,6 +29,7 @@ import static org.junit.Assert.fail; import com.google.cloud.Timestamp; +import com.google.cloud.Tuple; import com.google.cloud.datastore.AggregationQuery; import com.google.cloud.datastore.Batch; import com.google.cloud.datastore.BooleanValue; @@ -335,57 +336,82 @@ public void testNewTransactionCommit() { } @Test - public void testTransactionWithRead() { - Transaction transaction = DATASTORE.newTransaction(); - assertNull(transaction.get(KEY3)); - transaction.add(ENTITY3); - transaction.commit(); + public void testTransactionWithRead() throws Exception { + StatementExecutor statementExecutor = new StatementExecutor(); + Transaction baseTransaction = DATASTORE.newTransaction(); + assertNull(baseTransaction.get(KEY3)); + baseTransaction.add(ENTITY3); + baseTransaction.commit(); assertEquals(ENTITY3, DATASTORE.get(KEY3)); - transaction = DATASTORE.newTransaction(); - assertEquals(ENTITY3, transaction.get(KEY3)); - // update entity3 during the transaction - DATASTORE.put(Entity.newBuilder(ENTITY2).clear().set("from", "datastore").build()); - transaction.update(Entity.newBuilder(ENTITY2).clear().set("from", "transaction").build()); - try { - transaction.commit(); - fail("Expecting a failure"); - } catch (DatastoreException expected) { - assertEquals("ABORTED", expected.getReason()); - } + Transaction transaction = DATASTORE.newTransaction(); + statementExecutor.execute( + Tuple.of("T1", () -> assertEquals(ENTITY3, transaction.get(KEY3))), + // update entity3 during the transaction, will be blocked in case of pessimistic concurrency + Tuple.of( + "T2", + () -> + DATASTORE.put(Entity.newBuilder(ENTITY3).clear().set("from", "datastore").build())), + Tuple.of( + "T1", + () -> + transaction.update( + Entity.newBuilder(ENTITY3).clear().set("from", "transaction").build())), + Tuple.of("T1", transaction::commit) // T1 will throw error in case of optimistic concurrency + ); + + boolean t1AllPassed = statementExecutor.didAllPass("T1"); + boolean t2AllPassed = statementExecutor.didAllPass("T2"); + // If two transactions conflict with each other, the database guarantees that only + // one can commit successfully at a time. Please refer to StatementExecutor class for more info. + // Using XOR to ensure that only one of transaction group is successful, + boolean onlyOneTransactionIsSuccessful = t1AllPassed ^ t2AllPassed; + + assertThat(onlyOneTransactionIsSuccessful).isTrue(); } @Test - public void testTransactionWithQuery() { + public void testTransactionWithQuery() throws Exception { + StatementExecutor statementExecutor = new StatementExecutor(); Query query = Query.newEntityQueryBuilder() .setKind(KIND2) .setFilter(PropertyFilter.hasAncestor(KEY2)) .setNamespace(NAMESPACE) .build(); - Transaction transaction = DATASTORE.newTransaction(); - QueryResults results = transaction.run(query); - assertTrue(results.hasNext()); - assertEquals(ENTITY2, results.next()); - assertFalse(results.hasNext()); - transaction.add(ENTITY3); - transaction.commit(); + Transaction baseTransaction = DATASTORE.newTransaction(); + QueryResults baseResults = baseTransaction.run(query); + assertTrue(baseResults.hasNext()); + assertEquals(ENTITY2, baseResults.next()); + assertFalse(baseResults.hasNext()); + baseTransaction.add(ENTITY3); + baseTransaction.commit(); assertEquals(ENTITY3, DATASTORE.get(KEY3)); - transaction = DATASTORE.newTransaction(); - results = transaction.run(query); - assertTrue(results.hasNext()); - assertEquals(ENTITY2, results.next()); - assertFalse(results.hasNext()); - transaction.delete(ENTITY3.getKey()); - // update entity2 during the transaction - DATASTORE.put(Entity.newBuilder(ENTITY2).clear().build()); - try { - transaction.commit(); - fail("Expecting a failure"); - } catch (DatastoreException expected) { - assertEquals("ABORTED", expected.getReason()); - } + Transaction transaction = DATASTORE.newTransaction(); + statementExecutor.execute( + Tuple.of( + "T1", + () -> { + QueryResults results = transaction.run(query); + assertTrue(results.hasNext()); + assertEquals(ENTITY2, results.next()); + assertFalse(results.hasNext()); + }), + Tuple.of("T1", () -> transaction.delete(ENTITY3.getKey())), + // update entity2 during the transaction, will be blocked in case of pessimistic concurrency + Tuple.of("T2", () -> DATASTORE.put(Entity.newBuilder(ENTITY2).clear().build())), + Tuple.of("T1", transaction::commit) // T1 will throw error in case of optimistic concurrency + ); + + boolean t1AllPassed = statementExecutor.didAllPass("T1"); + boolean t2AllPassed = statementExecutor.didAllPass("T2"); + // If two transactions conflict with each other, the database guarantees that only + // one can commit successfully at a time. Please refer to StatementExecutor class for more info. + // Using XOR to ensure that only one of transaction group is successful, + boolean onlyOneTransactionIsSuccessful = t1AllPassed ^ t2AllPassed; + + assertThat(onlyOneTransactionIsSuccessful).isTrue(); } @Test diff --git a/google-cloud-datastore/src/test/java/com/google/cloud/datastore/it/StatementExecutor.java b/google-cloud-datastore/src/test/java/com/google/cloud/datastore/it/StatementExecutor.java new file mode 100644 index 000000000..c8ded3d89 --- /dev/null +++ b/google-cloud-datastore/src/test/java/com/google/cloud/datastore/it/StatementExecutor.java @@ -0,0 +1,91 @@ +/* + * Copyright 2023 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 + * + * https://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.google.cloud.datastore.it; + +import static java.util.concurrent.TimeUnit.SECONDS; + +import com.google.cloud.Tuple; +import com.google.cloud.datastore.DatastoreException; +import com.google.common.collect.ArrayListMultimap; +import com.google.common.collect.Multimap; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.TimeoutException; + +/** + * An executor class to handle interleaved transactions. + * + *

It executes statements (under multiple transactions) and record their failures under a groupId + * provided by users. + */ +class StatementExecutor { + + private final Multimap failures = ArrayListMultimap.create(); + + /** + * Executes a list of {@link Statement} one by one and record their failures under the groupId. In + * case of pessimistic concurrency, a statement will be blocked and cause delay until another + * transaction which was started earlier is committed. In case of optimistic concurrency, both + * transaction can perform their operation simultaneously, but the one which commits first will be + * a winner and other one will get an error on commit operation indicating a need for retry. + * + * @param tuples A {@link Statement(String, String) Tuple(<String, Statement>)} has a + * groupId of {@link String} type and a {@link Statement} to execute. + */ + @SafeVarargs + final void execute(Tuple... tuples) throws Exception { + ExecutorService executorService = Executors.newSingleThreadExecutor(); + for (Tuple tuple : tuples) { + String groupId = tuple.x(); + Statement statement = tuple.y(); + Future future = executorService.submit(statement::execute); + try { + // waiting for statement to execute + future.get(10, SECONDS); + } catch (Exception exception) { + future.cancel(true); + if (transactionConflict(exception)) { + failures.put(groupId, exception); + } else { + throw exception; + } + } + } + executorService.shutdown(); + } + + boolean didAllPass(String groupId) { + return failures.get(groupId).isEmpty(); + } + + private boolean transactionConflict(Exception exception) { + if (exception instanceof TimeoutException) { // timed out coz of pessimistic concurrency delay + return true; + } + return exception instanceof ExecutionException + && exception.getCause().getClass() == DatastoreException.class + && exception + .getMessage() + .contains("contention"); // exception raise coz of optimistic concurrency + } + + interface Statement { + void execute(); + } +} From 58c8585e224a883e62503ad4f8cd83266e45cef5 Mon Sep 17 00:00:00 2001 From: "gcf-owl-bot[bot]" <78513119+gcf-owl-bot[bot]@users.noreply.github.com> Date: Fri, 19 May 2023 12:02:03 -0400 Subject: [PATCH 09/14] build: migrate release scripts (#1799) (#1080) Source-Link: https://github.com/googleapis/synthtool/commit/1fd6dff029bb3d873a4780e616388f802f086907 Post-Processor: gcr.io/cloud-devrel-public-resources/owlbot-java:latest@sha256:ad9cabee4c022f1aab04a71332369e0c23841062124818a4490f73337f790337 Co-authored-by: Owl Bot --- .github/.OwlBot.lock.yaml | 2 +- .github/release-trigger.yml | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/.OwlBot.lock.yaml b/.github/.OwlBot.lock.yaml index 35478afe3..aadf54f64 100644 --- a/.github/.OwlBot.lock.yaml +++ b/.github/.OwlBot.lock.yaml @@ -13,4 +13,4 @@ # limitations under the License. docker: image: gcr.io/cloud-devrel-public-resources/owlbot-java:latest - digest: sha256:8dd8395defb6a5069b0b10c435058bf13980606ba1967e2b3925ed50fc3cb22f + digest: sha256:ad9cabee4c022f1aab04a71332369e0c23841062124818a4490f73337f790337 diff --git a/.github/release-trigger.yml b/.github/release-trigger.yml index d4ca94189..4d7c5dc57 100644 --- a/.github/release-trigger.yml +++ b/.github/release-trigger.yml @@ -1 +1,2 @@ enabled: true +multiScmName: java-datastore From 47df1b8a4b54eae0bb42e261e02d64aee7b95e7a Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 25 May 2023 15:58:07 +0200 Subject: [PATCH 10/14] deps: update dependency com.google.cloud:google-cloud-shared-dependencies to v3.10.0 (#1085) --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 71b78eec7..ad5d03f66 100644 --- a/pom.xml +++ b/pom.xml @@ -151,7 +151,7 @@ com.google.cloud google-cloud-shared-dependencies - 3.9.0 + 3.10.0 pom import From 95455e064f158371c5304732b9f7f542f7cb1a1a Mon Sep 17 00:00:00 2001 From: kolea2 <45548808+kolea2@users.noreply.github.com> Date: Thu, 25 May 2023 17:29:06 +0000 Subject: [PATCH 11/14] test: use ITDatastoreConceptsTest for graalvm testing (#1083) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * test: use ITDatastoreConceptsTest for graalvm testing * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * add comment to index.yaml * add header --------- Co-authored-by: Owl Bot --- datastore-v1-proto-client/pom.xml | 10 + google-cloud-datastore/pom.xml | 12 + .../datastore/it/ITDatastoreConceptsTest.java | 996 ++++++++++++++++++ .../src/test/resources/index.yaml | 48 + 4 files changed, 1066 insertions(+) create mode 100644 google-cloud-datastore/src/test/java/com/google/cloud/datastore/it/ITDatastoreConceptsTest.java create mode 100644 google-cloud-datastore/src/test/resources/index.yaml diff --git a/datastore-v1-proto-client/pom.xml b/datastore-v1-proto-client/pom.xml index e2bcefbc2..755bb5b0d 100644 --- a/datastore-v1-proto-client/pom.xml +++ b/datastore-v1-proto-client/pom.xml @@ -121,4 +121,14 @@ + + + native + + + true + + + + diff --git a/google-cloud-datastore/pom.xml b/google-cloud-datastore/pom.xml index c56273e38..14a3007f9 100644 --- a/google-cloud-datastore/pom.xml +++ b/google-cloud-datastore/pom.xml @@ -159,4 +159,16 @@ + + + native + + + com.google.cloud.datastore.it.ITDatastoreConceptsTest + + + diff --git a/google-cloud-datastore/src/test/java/com/google/cloud/datastore/it/ITDatastoreConceptsTest.java b/google-cloud-datastore/src/test/java/com/google/cloud/datastore/it/ITDatastoreConceptsTest.java new file mode 100644 index 000000000..b8ebd277a --- /dev/null +++ b/google-cloud-datastore/src/test/java/com/google/cloud/datastore/it/ITDatastoreConceptsTest.java @@ -0,0 +1,996 @@ +/* + * Copyright 2023 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 + * + * https://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.google.cloud.datastore.it; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import com.google.cloud.Timestamp; +import com.google.cloud.datastore.Cursor; +import com.google.cloud.datastore.Datastore; +import com.google.cloud.datastore.DatastoreException; +import com.google.cloud.datastore.DatastoreOptions; +import com.google.cloud.datastore.Entity; +import com.google.cloud.datastore.EntityQuery; +import com.google.cloud.datastore.FullEntity; +import com.google.cloud.datastore.IncompleteKey; +import com.google.cloud.datastore.Key; +import com.google.cloud.datastore.KeyFactory; +import com.google.cloud.datastore.KeyQuery; +import com.google.cloud.datastore.ListValue; +import com.google.cloud.datastore.PathElement; +import com.google.cloud.datastore.ProjectionEntity; +import com.google.cloud.datastore.Query; +import com.google.cloud.datastore.QueryResults; +import com.google.cloud.datastore.ReadOption; +import com.google.cloud.datastore.StringValue; +import com.google.cloud.datastore.StructuredQuery; +import com.google.cloud.datastore.StructuredQuery.CompositeFilter; +import com.google.cloud.datastore.StructuredQuery.OrderBy; +import com.google.cloud.datastore.StructuredQuery.PropertyFilter; +import com.google.cloud.datastore.Transaction; +import com.google.cloud.datastore.testing.RemoteDatastoreHelper; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Iterators; +import com.google.datastore.v1.TransactionOptions; +import com.google.datastore.v1.TransactionOptions.ReadOnly; +import java.time.LocalDateTime; +import java.time.Month; +import java.time.ZoneOffset; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +/* + * Test created based on ConceptsTest to run against GraalVM checks + */ +public class ITDatastoreConceptsTest { + private static final RemoteDatastoreHelper HELPER = RemoteDatastoreHelper.create(); + private static final DatastoreOptions OPTIONS = HELPER.getOptions(); + private static final FullEntity TEST_FULL_ENTITY = FullEntity.newBuilder().build(); + private Datastore datastore; + private KeyFactory keyFactory; + private Key taskKey; + private Entity testEntity; + private Timestamp startDate; + private Timestamp endDate; + private Timestamp includedDate; + + private static final String TASK_CONCEPTS = "TaskConcepts"; + + /** + * Initializes Datastore and cleans out any residual values. Also initializes global variables + * used for testing. + */ + @Before + public void setUp() { + datastore = OPTIONS.getService(); + StructuredQuery query = Query.newKeyQueryBuilder().build(); + QueryResults result = datastore.run(query); + datastore.delete(Iterators.toArray(result, Key.class)); + keyFactory = datastore.newKeyFactory().setKind(TASK_CONCEPTS); + taskKey = keyFactory.newKey("some-arbitrary-key"); + testEntity = Entity.newBuilder(taskKey, TEST_FULL_ENTITY).build(); + startDate = + Timestamp.ofTimeSecondsAndNanos( + LocalDateTime.of(1990, Month.JANUARY, 1, 1, 1, 1) + .toInstant(ZoneOffset.UTC) + .getEpochSecond(), + 0); + endDate = + Timestamp.ofTimeSecondsAndNanos( + LocalDateTime.of(2000, Month.JANUARY, 1, 1, 1, 1) + .toInstant(ZoneOffset.UTC) + .getEpochSecond(), + 0); + includedDate = + Timestamp.ofTimeSecondsAndNanos( + LocalDateTime.of(1999, Month.DECEMBER, 31, 1, 1, 1) + .toInstant(ZoneOffset.UTC) + .getEpochSecond(), + 0); + setUpQueryTests(); + } + + @After + public void tearDown() { + KeyQuery taskQuery = Query.newKeyQueryBuilder().setKind(TASK_CONCEPTS).build(); + Key[] taskKeysToDelete = Iterators.toArray(datastore.run(taskQuery), Key.class); + datastore.delete(taskKeysToDelete); + } + + private void assertValidKey(Key taskKey) { + datastore.put(Entity.newBuilder(taskKey, TEST_FULL_ENTITY).build()); + } + + private void assertValidEntity(Entity original) { + datastore.put(original); + assertEquals(original, datastore.get(original.getKey())); + } + + private List setUpBatchTests(Key taskKey1, Key taskKey2) { + Entity task1 = + Entity.newBuilder(taskKey1) + .set("category", "Personal") + .set("done", false) + .set("priority", 4) + .set("description", "Learn Cloud Datastore") + .build(); + Entity task2 = + Entity.newBuilder(taskKey2) + .set("category", "Personal") + .set("done", false) + .set("priority", 5) + .set("description", "Integrate Cloud Datastore") + .build(); + datastore.put(task1, task2); + return ImmutableList.of(task1, task2); + } + + private void setUpQueryTests() { + Key taskKey = + datastore + .newKeyFactory() + .setKind(TASK_CONCEPTS) + .addAncestors(PathElement.of("TaskList", "default")) + .newKey("someTask"); + datastore.put( + Entity.newBuilder(taskKey) + .set("category", "Personal") + .set("done", false) + .set("completed", false) + .set("priority", 4) + .set("created", includedDate) + .set("percent_complete", 10.0) + .set( + "description", + StringValue.newBuilder("Learn Cloud Datastore").setExcludeFromIndexes(true).build()) + .set("tag", "fun", "l", "programming", "learn") + .build()); + } + + private void assertValidQuery(Query query) { + QueryResults results = datastore.run(query); + assertTrue(results.hasNext()); + results.next(); + assertFalse(results.hasNext()); + } + + private void assertInvalidQuery(Query query) { + try { + datastore.run(query); + fail("should not reach here"); + } catch (DatastoreException ignored) { + } + } + + private List setUpTransferTests() { + KeyFactory keyFactory = datastore.newKeyFactory().setKind("People"); + Key from = keyFactory.newKey("from"); + Key to = keyFactory.newKey("to"); + datastore.put(Entity.newBuilder(from).set("balance", 100).build()); + datastore.put(Entity.newBuilder(to).set("balance", 0).build()); + return ImmutableList.of(from, to); + } + + private void assertSuccessfulTransfer(Key from, Key to) { + assertEquals(90, datastore.get(from).getLong("balance")); + assertEquals(10, datastore.get(to).getLong("balance")); + } + + @Test + public void testIncompleteKey() { + KeyFactory keyFactory = datastore.newKeyFactory().setKind(TASK_CONCEPTS); + Key taskKey = datastore.allocateId(keyFactory.newKey()); + assertValidKey(taskKey); + } + + @Test + public void testNamedKey() { + Key taskKey = datastore.newKeyFactory().setKind(TASK_CONCEPTS).newKey("sampleTask"); + assertValidKey(taskKey); + } + + @Test + public void testKeyWithParent() { + Key taskKey = + datastore + .newKeyFactory() + .addAncestors(PathElement.of("TaskList", "default")) + .setKind(TASK_CONCEPTS) + .newKey("sampleTask"); + assertValidKey(taskKey); + } + + @Test + public void testKeyWithMultilevelParent() { + KeyFactory keyFactory = + datastore + .newKeyFactory() + .addAncestors(PathElement.of("User", "Alice"), PathElement.of("TaskList", "default")) + .setKind(TASK_CONCEPTS); + Key taskKey = keyFactory.newKey("sampleTask"); + assertValidKey(taskKey); + } + + @Test + public void testEntityWithParent() { + Key taskKey = + datastore + .newKeyFactory() + .addAncestors(PathElement.of("TaskList", "default")) + .setKind(TASK_CONCEPTS) + .newKey("sampleTask"); + Entity task = + Entity.newBuilder(taskKey) + .set("category", "Personal") + .set("done", false) + .set("priority", 4) + .set("description", "Learn Cloud Datastore") + .build(); + assertValidEntity(task); + } + + @Test + public void testProperties() { + Entity task = + Entity.newBuilder(taskKey) + .set("category", "Personal") + .set("created", Timestamp.now()) + .set("done", false) + .set("priority", 4) + .set("percent_complete", 10.0) + .set( + "description", + StringValue.newBuilder("Learn Cloud Datastore").setExcludeFromIndexes(true).build()) + .build(); + assertValidEntity(task); + } + + @Test + public void testArrayValue() { + Entity task = + Entity.newBuilder(taskKey) + .set("tags", "fun", "programming") + .set("collaborators", ListValue.of("alice", "bob")) + .build(); + assertValidEntity(task); + } + + @Test + public void testBasicEntity() { + Key taskKey = datastore.newKeyFactory().setKind(TASK_CONCEPTS).newKey("sampleTask"); + Entity task = + Entity.newBuilder(taskKey) + .set("category", "Personal") + .set("done", false) + .set("priority", 4) + .set("description", "Learn Cloud Datastore") + .build(); + assertValidEntity(task); + } + + @Test + public void testUpsert() { + Entity task = Entity.newBuilder(keyFactory.newKey("sampleTask")).build(); + datastore.put(task); + assertEquals(task, datastore.get(task.getKey())); + } + + @Test + public void testInsert() { + Key taskKey = datastore.add(FullEntity.newBuilder(keyFactory.newKey()).build()).getKey(); + assertEquals(FullEntity.newBuilder(taskKey).build(), datastore.get(taskKey)); + } + + @Test + public void testLookup() { + datastore.put(testEntity); + Entity task = datastore.get(taskKey); + assertEquals(testEntity, task); + } + + @Test + public void testUpdate() { + datastore.put(testEntity); + Entity task = Entity.newBuilder(datastore.get(taskKey)).set("priority", 5).build(); + datastore.update(task); + assertEquals(task, datastore.get(taskKey)); + } + + @Test + public void testDelete() { + datastore.put(testEntity); + datastore.delete(taskKey); + assertNull(datastore.get(taskKey)); + } + + @Test + public void testBatchUpsert() { + FullEntity task1 = + FullEntity.newBuilder(keyFactory.newKey()) + .set("category", "Personal") + .set("done", false) + .set("priority", 4) + .set("description", "Learn Cloud Datastore") + .build(); + FullEntity task2 = + Entity.newBuilder(keyFactory.newKey()) + .set("category", "Personal") + .set("done", false) + .set("priority", 5) + .set("description", "Integrate Cloud Datastore") + .build(); + List tasks = datastore.add(task1, task2); + Key taskKey1 = tasks.get(0).getKey(); + Key taskKey2 = tasks.get(1).getKey(); + assertEquals(Entity.newBuilder(taskKey1, task1).build(), datastore.get(taskKey1)); + assertEquals(Entity.newBuilder(taskKey2, task2).build(), datastore.get(taskKey2)); + } + + @Test + public void testBatchLookup() { + Key taskKey1 = keyFactory.newKey(1); + Key taskKey2 = keyFactory.newKey(2); + List expectedTasks = setUpBatchTests(taskKey1, taskKey2); + Iterator tasks = datastore.get(taskKey1, taskKey2); + assertEquals(expectedTasks.get(0), tasks.next()); + assertEquals(expectedTasks.get(1), tasks.next()); + } + + @Test + public void testBatchDelete() { + Key taskKey1 = keyFactory.newKey(1); + Key taskKey2 = keyFactory.newKey(2); + setUpBatchTests(taskKey1, taskKey2); + datastore.delete(taskKey1, taskKey2); + assertNull(datastore.get(taskKey1)); + assertNull(datastore.get(taskKey2)); + } + + @Test + public void testBasicQuery() { + Query query = + Query.newEntityQueryBuilder() + .setKind(TASK_CONCEPTS) + .setFilter( + CompositeFilter.and( + PropertyFilter.eq("done", false), PropertyFilter.ge("priority", 4))) + .setOrderBy(OrderBy.desc("priority")) + .build(); + assertValidQuery(query); + } + + @Test + public void testRunQuery() { + Query query = Query.newEntityQueryBuilder().setKind(TASK_CONCEPTS).build(); + QueryResults tasks = datastore.run(query); + assertNotNull(tasks.next()); + assertFalse(tasks.hasNext()); + } + + @Test + public void testPropertyFilter() { + Query query = + Query.newEntityQueryBuilder() + .setKind(TASK_CONCEPTS) + .setFilter(PropertyFilter.eq("done", false)) + .build(); + assertValidQuery(query); + } + + @Test + public void testCompositeFilter() { + Query query = + Query.newEntityQueryBuilder() + .setKind(TASK_CONCEPTS) + .setFilter( + CompositeFilter.and( + PropertyFilter.eq("done", false), PropertyFilter.eq("priority", 4))) + .build(); + assertValidQuery(query); + } + + @Test + public void testKeyFilter() { + Query query = + Query.newEntityQueryBuilder() + .setKind(TASK_CONCEPTS) + .setFilter(StructuredQuery.PropertyFilter.gt("__key__", keyFactory.newKey("someTask"))) + .build(); + assertValidQuery(query); + } + + @Test + public void testAscendingSort() { + Query query = + Query.newEntityQueryBuilder() + .setKind(TASK_CONCEPTS) + .setOrderBy(OrderBy.asc("created")) + .build(); + assertValidQuery(query); + } + + @Test + public void testDescendingSort() { + Query query = + Query.newEntityQueryBuilder() + .setKind(TASK_CONCEPTS) + .setOrderBy(OrderBy.desc("created")) + .build(); + assertValidQuery(query); + } + + @Test + public void testMultiSort() { + Query query = + Query.newEntityQueryBuilder() + .setKind(TASK_CONCEPTS) + .setOrderBy(OrderBy.desc("priority"), OrderBy.asc("created")) + .build(); + assertValidQuery(query); + } + + @Test + public void testKindlessQuery() { + Key lastSeenKey = keyFactory.newKey("a"); + + Query query = + Query.newEntityQueryBuilder().setFilter(PropertyFilter.gt("__key__", lastSeenKey)).build(); + assertValidQuery(query); + } + + @Test + public void testAncestorQuery() { + Query query = + Query.newEntityQueryBuilder() + .setKind(TASK_CONCEPTS) + .setFilter( + PropertyFilter.hasAncestor( + datastore.newKeyFactory().setKind("TaskList").newKey("default"))) + .build(); + assertValidQuery(query); + } + + @Test + public void testProjectionQuery() { + Query query = + Query.newProjectionEntityQueryBuilder() + .setKind(TASK_CONCEPTS) + .setProjection("priority", "percent_complete") + .build(); + assertValidQuery(query); + } + + @Test + public void testRunProjectionQuery() { + Query query = + Query.newProjectionEntityQueryBuilder() + .setKind(TASK_CONCEPTS) + .setProjection("priority", "percent_complete") + .build(); + List priorities = new LinkedList<>(); + List percentCompletes = new LinkedList<>(); + QueryResults tasks = datastore.run(query); + while (tasks.hasNext()) { + ProjectionEntity task = tasks.next(); + priorities.add(task.getLong("priority")); + percentCompletes.add(task.getDouble("percent_complete")); + } + assertEquals(ImmutableList.of(4L), priorities); + assertEquals(ImmutableList.of(10.0), percentCompletes); + } + + @Test + public void testKeysOnlyQuery() { + Query query = Query.newKeyQueryBuilder().setKind(TASK_CONCEPTS).build(); + assertValidQuery(query); + } + + @Test + public void testDistinctOnQuery() { + Query query = + Query.newProjectionEntityQueryBuilder() + .setKind(TASK_CONCEPTS) + .setProjection("category", "priority") + .setDistinctOn("category") + .setOrderBy(OrderBy.asc("category"), OrderBy.asc("priority")) + .build(); + assertValidQuery(query); + } + + @Test + public void testArrayValueInequalityRange() { + Query query = + Query.newEntityQueryBuilder() + .setKind(TASK_CONCEPTS) + .setFilter( + CompositeFilter.and( + PropertyFilter.gt("tag", "learn"), PropertyFilter.lt("tag", "math"))) + .build(); + QueryResults results = datastore.run(query); + assertFalse(results.hasNext()); + } + + @Test + public void testArrayValueEquality() { + Query query = + Query.newEntityQueryBuilder() + .setKind(TASK_CONCEPTS) + .setFilter( + CompositeFilter.and( + PropertyFilter.eq("tag", "fun"), PropertyFilter.eq("tag", "programming"))) + .build(); + assertValidQuery(query); + } + + @Test + public void testInequalityRange() { + Query query = + Query.newEntityQueryBuilder() + .setKind(TASK_CONCEPTS) + .setFilter( + CompositeFilter.and( + PropertyFilter.gt("created", startDate), PropertyFilter.lt("created", endDate))) + .build(); + assertValidQuery(query); + } + + @Test + public void testInequalityInvalid() { + Query query = + Query.newEntityQueryBuilder() + .setKind(TASK_CONCEPTS) + .setFilter( + CompositeFilter.and( + PropertyFilter.gt("created", startDate), PropertyFilter.gt("priority", 3))) + .build(); + assertInvalidQuery(query); + } + + @Test + public void testEqualAndInequalityRange() { + Query query = + Query.newEntityQueryBuilder() + .setKind(TASK_CONCEPTS) + .setFilter( + CompositeFilter.and( + PropertyFilter.eq("priority", 4), + PropertyFilter.gt("created", startDate), + PropertyFilter.lt("created", endDate))) + .build(); + assertValidQuery(query); + } + + @Test + public void testInequalitySort() { + Query query = + Query.newEntityQueryBuilder() + .setKind(TASK_CONCEPTS) + .setFilter(PropertyFilter.gt("priority", 3)) + .setOrderBy(OrderBy.asc("priority"), OrderBy.asc("created")) + .build(); + assertValidQuery(query); + } + + @Test + public void testInequalitySortInvalidNotSame() { + Query query = + Query.newEntityQueryBuilder() + .setKind(TASK_CONCEPTS) + .setFilter(PropertyFilter.gt("priority", 3)) + .setOrderBy(OrderBy.asc("created")) + .build(); + assertInvalidQuery(query); + } + + @Test + public void testInequalitySortInvalidNotFirst() { + Query query = + Query.newEntityQueryBuilder() + .setKind(TASK_CONCEPTS) + .setFilter(PropertyFilter.gt("priority", 3)) + .setOrderBy(OrderBy.asc("created"), OrderBy.asc("priority")) + .build(); + assertInvalidQuery(query); + } + + @Test + public void testLimit() { + Query query = Query.newEntityQueryBuilder().setKind(TASK_CONCEPTS).setLimit(5).build(); + assertValidQuery(query); + } + + @Test + public void testCursorPaging() { + datastore.put(testEntity); + Cursor nextPageCursor = cursorPaging(1, null); + assertNotNull(nextPageCursor); + nextPageCursor = cursorPaging(1, nextPageCursor); + assertNotNull(nextPageCursor); + } + + private Cursor cursorPaging(int pageSize, Cursor pageCursor) { + EntityQuery.Builder queryBuilder = + Query.newEntityQueryBuilder().setKind(TASK_CONCEPTS).setLimit(pageSize); + if (pageCursor != null) { + queryBuilder.setStartCursor(pageCursor); + } + QueryResults tasks = datastore.run(queryBuilder.build()); + while (tasks.hasNext()) { + Entity task = tasks.next(); + // do something with the task + } + Cursor nextPageCursor = tasks.getCursorAfter(); + return nextPageCursor; + } + + @Test + public void testEventualConsistentQuery() { + Query query = + Query.newEntityQueryBuilder() + .setKind(TASK_CONCEPTS) + .setFilter( + PropertyFilter.hasAncestor( + datastore.newKeyFactory().setKind("TaskList").newKey("default"))) + .build(); + datastore.run(query, ReadOption.eventualConsistency()); + assertValidQuery(query); + } + + @Test + public void testUnindexedPropertyQuery() { + Query query = + Query.newEntityQueryBuilder() + .setKind(TASK_CONCEPTS) + .setFilter(PropertyFilter.eq("description", "A task description")) + .build(); + QueryResults results = datastore.run(query); + assertFalse(results.hasNext()); + } + + @Test + public void testExplodingProperties() { + Entity task = + Entity.newBuilder(taskKey) + .set("tags", "fun", "programming", "learn") + .set("collaborators", "alice", "bob", "charlie") + .set("created", Timestamp.now()) + .build(); + assertValidEntity(task); + } + + @Test + public void testTransactionalUpdate() { + List keys = setUpTransferTests(); + transferFunds(keys.get(0), keys.get(1), 10); + assertSuccessfulTransfer(keys.get(0), keys.get(1)); + } + + void transferFunds(Key fromKey, Key toKey, long amount) { + Transaction txn = datastore.newTransaction(); + try { + List entities = txn.fetch(fromKey, toKey); + Entity from = entities.get(0); + Entity updatedFrom = + Entity.newBuilder(from).set("balance", from.getLong("balance") - amount).build(); + Entity to = entities.get(1); + Entity updatedTo = + Entity.newBuilder(to).set("balance", to.getLong("balance") + amount).build(); + txn.put(updatedFrom, updatedTo); + txn.commit(); + } finally { + if (txn.isActive()) { + txn.rollback(); + } + } + } + + @Test + public void testTransactionalRetry() { + List keys = setUpTransferTests(); + Key fromKey = keys.get(0); + Key toKey = keys.get(1); + int retries = 5; + while (true) { + try { + transferFunds(fromKey, toKey, 10); + break; + } catch (DatastoreException e) { + if (retries == 0) { + throw e; + } + --retries; + } + } + assertSuccessfulTransfer(keys.get(0), keys.get(1)); + } + + @Test + public void testTransactionalGetOrCreate() { + Entity task; + Transaction txn = datastore.newTransaction(); + try { + task = txn.get(taskKey); + if (task == null) { + task = Entity.newBuilder(taskKey).build(); + txn.put(task); + txn.commit(); + } + } finally { + if (txn.isActive()) { + txn.rollback(); + } + } + assertEquals(task, datastore.get(taskKey)); + } + + @Test + public void testTransactionalSingleEntityGroupReadOnly() { + + Key taskListKey = datastore.newKeyFactory().setKind("TaskList").newKey("default"); + Entity taskListEntity = Entity.newBuilder(taskListKey).build(); + datastore.put(taskListEntity); + Entity taskList; + QueryResults tasks; + Transaction txn = + datastore.newTransaction( + TransactionOptions.newBuilder().setReadOnly(ReadOnly.newBuilder().build()).build()); + try { + taskList = txn.get(taskListKey); + Query query = + Query.newEntityQueryBuilder() + .setKind(TASK_CONCEPTS) + .setFilter(PropertyFilter.hasAncestor(taskListKey)) + .build(); + tasks = txn.run(query); + txn.commit(); + } finally { + if (txn.isActive()) { + txn.rollback(); + } + } + assertEquals(taskListEntity, taskList); + assertNotNull(tasks.next()); + assertFalse(tasks.hasNext()); + } + + @Test + public void testNamespaceRunQuery() { + KeyFactory keyFactory = datastore.newKeyFactory().setKind("__namespace__"); + Key namespaceKey = keyFactory.newKey(OPTIONS.getNamespace()); + Query query = + Query.newKeyQueryBuilder() + .setKind("__namespace__") + .setFilter(CompositeFilter.and(PropertyFilter.eq("__key__", namespaceKey))) + .build(); + List namespaces = new ArrayList<>(); + QueryResults results = datastore.run(query); + while (results.hasNext()) { + namespaces.add(results.next().getName()); + } + assertEquals(ImmutableList.of(OPTIONS.getNamespace()), namespaces); + } + + @Test + public void testKindRunQuery() { + Query query = Query.newKeyQueryBuilder().setKind("__kind__").build(); + List kinds = new ArrayList<>(); + QueryResults results = datastore.run(query); + while (results.hasNext()) { + kinds.add(results.next().getName()); + } + assertEquals(ImmutableList.of(TASK_CONCEPTS), kinds); + } + + @Test + public void testPropertyRunQuery() { + Query query = Query.newKeyQueryBuilder().setKind("__property__").build(); + QueryResults keys = datastore.run(query); + Map> propertiesByKind = new HashMap<>(); + while (keys.hasNext()) { + Key key = keys.next(); + String kind = key.getParent().getName(); + String propertyName = key.getName(); + Collection properties = propertiesByKind.computeIfAbsent(kind, k -> new HashSet<>()); + properties.add(propertyName); + } + Map> expected = + ImmutableMap.of( + TASK_CONCEPTS, + ImmutableSet.of( + "done", "category", "completed", "priority", "created", "percent_complete", "tag")); + assertEquals(expected, propertiesByKind); + } + + @Test + public void testPropertyByKindRunQuery() { + Key key = datastore.newKeyFactory().setKind("__kind__").newKey(TASK_CONCEPTS); + Query query = + Query.newEntityQueryBuilder() + .setKind("__property__") + .setFilter(PropertyFilter.hasAncestor(key)) + .build(); + QueryResults results = datastore.run(query); + Map> representationsByProperty = new HashMap<>(); + while (results.hasNext()) { + Entity result = results.next(); + String propertyName = result.getKey().getName(); + List representations = result.getList("property_representation"); + Collection currentRepresentations = + representationsByProperty.computeIfAbsent(propertyName, k -> new HashSet<>()); + for (StringValue value : representations) { + currentRepresentations.add(value.get()); + } + } + Map> expected = + ImmutableMap.>builder() + .put("category", Collections.singleton("STRING")) + .put("done", Collections.singleton("BOOLEAN")) + .put("completed", Collections.singleton("BOOLEAN")) + .put("priority", Collections.singleton("INT64")) + .put("created", Collections.singleton("INT64")) + .put("percent_complete", Collections.singleton("DOUBLE")) + .put("tag", Collections.singleton("STRING")) + .build(); + assertEquals(expected, representationsByProperty); + } + + @Test + public void testPropertyFilteringRunQuery() { + Key startKey = + datastore + .newKeyFactory() + .setKind("__property__") + .addAncestors(PathElement.of("__kind__", TASK_CONCEPTS)) + .newKey("priority"); + Query query = + Query.newKeyQueryBuilder() + .setKind("__property__") + .setFilter(PropertyFilter.ge("__key__", startKey)) + .build(); + Map> propertiesByKind = new HashMap<>(); + QueryResults keys = datastore.run(query); + while (keys.hasNext()) { + Key key = keys.next(); + String kind = key.getParent().getName(); + String propertyName = key.getName(); + Collection properties = propertiesByKind.computeIfAbsent(kind, k -> new HashSet<>()); + properties.add(propertyName); + } + Map> expected = + ImmutableMap.of(TASK_CONCEPTS, ImmutableSet.of("priority", "tag")); + assertEquals(expected, propertiesByKind); + } + + @Test + public void testEqQuerySorted() { + Query query = + Query.newEntityQueryBuilder() + .setKind(TASK_CONCEPTS) + .setFilter(PropertyFilter.eq("tag", "learn")) + .setOrderBy(OrderBy.asc("tag")) + .build(); + assertValidQuery(query); + } + + private void setUpQueryTestsRealBackend() { + Key taskKey = + datastore + .newKeyFactory() + .setKind(TASK_CONCEPTS) + .addAncestors(PathElement.of("TaskList", "default")) + .newKey("someTask"); + datastore.put( + Entity.newBuilder(taskKey) + .set("category", "Personal") + .set("done", false) + .set("completed", false) + .set("priority", 4) + .set("created", includedDate) + .set("percent_complete", 10.0) + .set( + "description", + StringValue.newBuilder("Learn Cloud Datastore").setExcludeFromIndexes(true).build()) + .set("tag", "fun", "l", "programming", "learn") + .build()); + } + + @Test + public void testInQuery() { + setUpQueryTestsRealBackend(); + Query query = + Query.newEntityQueryBuilder() + .setKind(TASK_CONCEPTS) + .setFilter(PropertyFilter.in("tag", ListValue.of("learn", "study"))) + .build(); + assertValidQuery(query); + } + + @Test + public void testNotEqualsQuery() { + setUpQueryTestsRealBackend(); + Query query = + Query.newEntityQueryBuilder() + .setKind(TASK_CONCEPTS) + .setFilter(PropertyFilter.neq("category", "Work")) + .build(); + assertValidQuery(query); + } + + @Test + public void testNotInQuery() { + setUpQueryTestsRealBackend(); + Query query = + Query.newEntityQueryBuilder() + .setKind(TASK_CONCEPTS) + .setFilter(PropertyFilter.not_in("category", ListValue.of("Work", "Chores", "School"))) + .build(); + assertValidQuery(query); + } + + @Test + public void testInQuerySorted() { + setUpQueryTestsRealBackend(); + Query query = + Query.newEntityQueryBuilder() + .setKind(TASK_CONCEPTS) + .setFilter(PropertyFilter.in("tag", ListValue.of("learn", "study"))) + .setOrderBy(OrderBy.asc("tag")) + .build(); + assertValidQuery(query); + } + + @Test + public void testStaleReads() throws InterruptedException { + setUpQueryTestsRealBackend(); + // waiting for 6 seconds, so that we can query with read time of 5 seconds ago + TimeUnit.SECONDS.sleep(6); + Key taskKey = + datastore + .newKeyFactory() + .setKind(TASK_CONCEPTS) + .addAncestors(PathElement.of("TaskList", "default")) + .newKey("someTask"); + + Timestamp fiveSecondsAgo = + Timestamp.ofTimeSecondsAndNanos(Timestamp.now().getSeconds() - 5L, 0); + // Create a readOption with read time fiveSecondsAgo + ReadOption readOption = ReadOption.readTime(fiveSecondsAgo); + // Use the readOption to Fetch entity + Entity entity = datastore.get(taskKey, readOption); + + // Use the readOption to Query kind Task + Query query = Query.newEntityQueryBuilder().setKind(TASK_CONCEPTS).setLimit(10).build(); + assertValidQuery(query); + } +} diff --git a/google-cloud-datastore/src/test/resources/index.yaml b/google-cloud-datastore/src/test/resources/index.yaml new file mode 100644 index 000000000..ff1b08626 --- /dev/null +++ b/google-cloud-datastore/src/test/resources/index.yaml @@ -0,0 +1,48 @@ +# Copyright 2023 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. + +# one time index creation is required to run ITDatastoreConceptsTest +# see https://cloud.google.com/sdk/gcloud/reference/datastore/indexes/create for more details +indexes: + - kind: TaskConcepts + properties: + - name: done + - name: priority + direction: desc + - kind: TaskConcepts + properties: + - name: tag + - name: tag + - kind: TaskConcepts + properties: + - name: priority + - name: created + - kind: TaskConcepts + properties: + - name: category + - name: priority + - kind: TaskConcepts + properties: + - name: priority + direction: desc + - name: created + - kind: TaskConcepts + properties: + - name: percent_complete + - name: priority + - kind: TaskConcepts + properties: + - name: done + - name: priority + direction: desc \ No newline at end of file From 9e966506c1e860f10e82d34bd6a705c1cae71764 Mon Sep 17 00:00:00 2001 From: Prateek Date: Fri, 26 May 2023 10:06:19 +0530 Subject: [PATCH 12/14] docs: Marking Transaction, Batch and DatastoreBatchWriter class with 'NotThreadSafe' annotation (#1082) * doc: Marking Transaction, Batch and DatastoreBatchWriter class with @NotThreadSafe annotation * fix lint * adding jsr dependency explicitly * Empty commit * fixing casing and punctuation. * fix lint --- google-cloud-datastore/pom.xml | 4 ++++ .../main/java/com/google/cloud/datastore/Batch.java | 9 +++++++++ .../google/cloud/datastore/DatastoreBatchWriter.java | 9 +++++++++ .../java/com/google/cloud/datastore/Transaction.java | 12 ++++++++++-- 4 files changed, 32 insertions(+), 2 deletions(-) diff --git a/google-cloud-datastore/pom.xml b/google-cloud-datastore/pom.xml index 14a3007f9..a086383be 100644 --- a/google-cloud-datastore/pom.xml +++ b/google-cloud-datastore/pom.xml @@ -106,6 +106,10 @@ io.opencensus opencensus-api + + com.google.code.findbugs + jsr305 + diff --git a/google-cloud-datastore/src/main/java/com/google/cloud/datastore/Batch.java b/google-cloud-datastore/src/main/java/com/google/cloud/datastore/Batch.java index ee1c48db2..eb4abd854 100644 --- a/google-cloud-datastore/src/main/java/com/google/cloud/datastore/Batch.java +++ b/google-cloud-datastore/src/main/java/com/google/cloud/datastore/Batch.java @@ -17,6 +17,7 @@ package com.google.cloud.datastore; import java.util.List; +import javax.annotation.concurrent.NotThreadSafe; /** * An interface to represent a batch of write operations. Any write operation that is applied on a @@ -32,7 +33,15 @@ * batch.add(entity2, entity3); * batch.submit(); * } + * + *

WARNING: This class maintains an internal state in terms of {@link + * java.util.LinkedHashMap} and {@link java.util.LinkedHashSet} which gets updated on every method + * call performing CRUD operations to record the mutations. Since {@link java.util.LinkedHashMap} is + * not thread safe as per its documentation, + * This class too should not be treated as a thread safe class. */ +@NotThreadSafe public interface Batch extends DatastoreBatchWriter { interface Response { diff --git a/google-cloud-datastore/src/main/java/com/google/cloud/datastore/DatastoreBatchWriter.java b/google-cloud-datastore/src/main/java/com/google/cloud/datastore/DatastoreBatchWriter.java index d03d90af8..db4bd3179 100644 --- a/google-cloud-datastore/src/main/java/com/google/cloud/datastore/DatastoreBatchWriter.java +++ b/google-cloud-datastore/src/main/java/com/google/cloud/datastore/DatastoreBatchWriter.java @@ -17,11 +17,20 @@ package com.google.cloud.datastore; import java.util.List; +import javax.annotation.concurrent.NotThreadSafe; /** * An interface to represent a batch of write operations. All write operation for a batch writer * will be applied to the Datastore in one RPC call. + * + *

WARNING: This class maintains an internal state in terms of {@link + * java.util.LinkedHashMap} and {@link java.util.LinkedHashSet} which gets updated on every method + * call performing CRUD operations to record the mutations. Since {@link java.util.LinkedHashMap} is + * not thread safe as per its documentation, + * This class too should not be treated as a thread safe class. */ +@NotThreadSafe public interface DatastoreBatchWriter extends DatastoreWriter { /** diff --git a/google-cloud-datastore/src/main/java/com/google/cloud/datastore/Transaction.java b/google-cloud-datastore/src/main/java/com/google/cloud/datastore/Transaction.java index 9880b4748..69c18d75c 100644 --- a/google-cloud-datastore/src/main/java/com/google/cloud/datastore/Transaction.java +++ b/google-cloud-datastore/src/main/java/com/google/cloud/datastore/Transaction.java @@ -19,14 +19,15 @@ import com.google.protobuf.ByteString; import java.util.Iterator; import java.util.List; +import javax.annotation.concurrent.NotThreadSafe; /** * A Google cloud datastore transaction. Similar to {@link Batch} any write operation that is * applied on a transaction will only be sent to the Datastore upon {@link #commit}. A call to * {@link #rollback} will invalidate the transaction and discard the changes. Any read operation * that is done by a transaction will be part of it and therefore a {@code commit} is guaranteed to - * fail if an entity was modified outside of the transaction after it was read. Write operation on - * this transaction will not be reflected by read operation (as the changes are only sent to the + * fail if an entity was modified outside the transaction after it was read. Write operation on this + * transaction will not be reflected by read operation (as the changes are only sent to the * Datastore upon {@code commit}. A usage example: * *

{@code
@@ -52,7 +53,14 @@
  *
  * @see Google Cloud
  *     Datastore transactions
+ *     

WARNING: This class maintains an internal state in terms of {@link + * java.util.LinkedHashMap} and {@link java.util.LinkedHashSet} which gets updated on every + * method call performing CRUD operations to record the mutations. Since {@link + * java.util.LinkedHashMap} is not thread safe as per its documentation, + * This class too should not be treated as a thread safe class. */ +@NotThreadSafe public interface Transaction extends DatastoreBatchWriter, DatastoreReaderWriter { interface Response { From e3ad86614a2462054bfb800613f2456f6f98102d Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 29 May 2023 09:27:53 +0200 Subject: [PATCH 13/14] deps: update dependency com.google.cloud:google-cloud-shared-dependencies to v3.10.1 (#1086) --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index ad5d03f66..d2158546b 100644 --- a/pom.xml +++ b/pom.xml @@ -151,7 +151,7 @@ com.google.cloud google-cloud-shared-dependencies - 3.10.0 + 3.10.1 pom import From 33dc935503fcdb69299d4f79aad5e4f5930bcad5 Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Mon, 29 May 2023 14:20:33 +0530 Subject: [PATCH 14/14] chore(main): release 2.14.7 (#1076) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- CHANGELOG.md | 16 ++++++++++++++++ datastore-v1-proto-client/pom.xml | 4 ++-- google-cloud-datastore-bom/pom.xml | 10 +++++----- google-cloud-datastore/pom.xml | 4 ++-- grpc-google-cloud-datastore-admin-v1/pom.xml | 4 ++-- pom.xml | 12 ++++++------ proto-google-cloud-datastore-admin-v1/pom.xml | 4 ++-- proto-google-cloud-datastore-v1/pom.xml | 4 ++-- versions.txt | 12 ++++++------ 9 files changed, 43 insertions(+), 27 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index da08db8f7..c29fa7871 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,21 @@ # Changelog +## [2.14.7](https://github.com/googleapis/java-datastore/compare/v2.14.6...v2.14.7) (2023-05-29) + + +### Documentation + +* Marking Transaction, Batch and DatastoreBatchWriter class with 'NotThreadSafe' annotation ([#1082](https://github.com/googleapis/java-datastore/issues/1082)) ([9e96650](https://github.com/googleapis/java-datastore/commit/9e966506c1e860f10e82d34bd6a705c1cae71764)) + + +### Dependencies + +* Update dependency com.google.cloud:google-cloud-shared-dependencies to v3.10.0 ([#1085](https://github.com/googleapis/java-datastore/issues/1085)) ([47df1b8](https://github.com/googleapis/java-datastore/commit/47df1b8a4b54eae0bb42e261e02d64aee7b95e7a)) +* Update dependency com.google.cloud:google-cloud-shared-dependencies to v3.10.1 ([#1086](https://github.com/googleapis/java-datastore/issues/1086)) ([e3ad866](https://github.com/googleapis/java-datastore/commit/e3ad86614a2462054bfb800613f2456f6f98102d)) +* Update dependency com.google.errorprone:error_prone_core to v2.19.1 ([#1069](https://github.com/googleapis/java-datastore/issues/1069)) ([2390016](https://github.com/googleapis/java-datastore/commit/239001682bd1284be39d4646ce0594274070c143)) +* Update dependency org.graalvm.buildtools:junit-platform-native to v0.9.22 ([#1074](https://github.com/googleapis/java-datastore/issues/1074)) ([c0cc456](https://github.com/googleapis/java-datastore/commit/c0cc4565cc0e34098f5bc97c031ae671af44fcf3)) +* Update dependency org.graalvm.buildtools:native-maven-plugin to v0.9.22 ([#1075](https://github.com/googleapis/java-datastore/issues/1075)) ([a4db895](https://github.com/googleapis/java-datastore/commit/a4db89502e9611bf5f9760bfceb1025cc99a9830)) + ## [2.14.6](https://github.com/googleapis/java-datastore/compare/v2.14.5...v2.14.6) (2023-05-09) diff --git a/datastore-v1-proto-client/pom.xml b/datastore-v1-proto-client/pom.xml index 755bb5b0d..2856a0169 100644 --- a/datastore-v1-proto-client/pom.xml +++ b/datastore-v1-proto-client/pom.xml @@ -19,12 +19,12 @@ 4.0.0 com.google.cloud.datastore datastore-v1-proto-client - 2.14.7-SNAPSHOT + 2.14.7 com.google.cloud google-cloud-datastore-parent - 2.14.7-SNAPSHOT + 2.14.7 jar diff --git a/google-cloud-datastore-bom/pom.xml b/google-cloud-datastore-bom/pom.xml index 6dae71644..daa66d945 100644 --- a/google-cloud-datastore-bom/pom.xml +++ b/google-cloud-datastore-bom/pom.xml @@ -3,7 +3,7 @@ 4.0.0 com.google.cloud google-cloud-datastore-bom - 2.14.7-SNAPSHOT + 2.14.7 pom com.google.cloud @@ -52,22 +52,22 @@ com.google.cloud google-cloud-datastore - 2.14.7-SNAPSHOT + 2.14.7 com.google.api.grpc grpc-google-cloud-datastore-admin-v1 - 2.14.7-SNAPSHOT + 2.14.7 com.google.api.grpc proto-google-cloud-datastore-v1 - 0.105.7-SNAPSHOT + 0.105.7 com.google.api.grpc proto-google-cloud-datastore-admin-v1 - 2.14.7-SNAPSHOT + 2.14.7 diff --git a/google-cloud-datastore/pom.xml b/google-cloud-datastore/pom.xml index a086383be..8196db8da 100644 --- a/google-cloud-datastore/pom.xml +++ b/google-cloud-datastore/pom.xml @@ -2,7 +2,7 @@ 4.0.0 google-cloud-datastore - 2.14.7-SNAPSHOT + 2.14.7 jar Google Cloud Datastore https://github.com/googleapis/java-datastore @@ -12,7 +12,7 @@ com.google.cloud google-cloud-datastore-parent - 2.14.7-SNAPSHOT + 2.14.7 google-cloud-datastore diff --git a/grpc-google-cloud-datastore-admin-v1/pom.xml b/grpc-google-cloud-datastore-admin-v1/pom.xml index 268b3ab78..142659867 100644 --- a/grpc-google-cloud-datastore-admin-v1/pom.xml +++ b/grpc-google-cloud-datastore-admin-v1/pom.xml @@ -4,13 +4,13 @@ 4.0.0 com.google.api.grpc grpc-google-cloud-datastore-admin-v1 - 2.14.7-SNAPSHOT + 2.14.7 grpc-google-cloud-datastore-admin-v1 GRPC library for google-cloud-datastore com.google.cloud google-cloud-datastore-parent - 2.14.7-SNAPSHOT + 2.14.7 diff --git a/pom.xml b/pom.xml index d2158546b..b0b6d9fbe 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ com.google.cloud google-cloud-datastore-parent pom - 2.14.7-SNAPSHOT + 2.14.7 Google Cloud Datastore Parent https://github.com/googleapis/java-datastore @@ -159,27 +159,27 @@ com.google.api.grpc proto-google-cloud-datastore-admin-v1 - 2.14.7-SNAPSHOT + 2.14.7 com.google.api.grpc grpc-google-cloud-datastore-admin-v1 - 2.14.7-SNAPSHOT + 2.14.7 com.google.cloud google-cloud-datastore - 2.14.7-SNAPSHOT + 2.14.7 com.google.api.grpc proto-google-cloud-datastore-v1 - 0.105.7-SNAPSHOT + 0.105.7 com.google.cloud.datastore datastore-v1-proto-client - 2.14.7-SNAPSHOT + 2.14.7 com.google.api.grpc diff --git a/proto-google-cloud-datastore-admin-v1/pom.xml b/proto-google-cloud-datastore-admin-v1/pom.xml index 5c1b10653..70bd9bb5f 100644 --- a/proto-google-cloud-datastore-admin-v1/pom.xml +++ b/proto-google-cloud-datastore-admin-v1/pom.xml @@ -4,13 +4,13 @@ 4.0.0 com.google.api.grpc proto-google-cloud-datastore-admin-v1 - 2.14.7-SNAPSHOT + 2.14.7 proto-google-cloud-datastore-admin-v1 Proto library for google-cloud-datastore com.google.cloud google-cloud-datastore-parent - 2.14.7-SNAPSHOT + 2.14.7 diff --git a/proto-google-cloud-datastore-v1/pom.xml b/proto-google-cloud-datastore-v1/pom.xml index 336513bb7..e8c1b8b3d 100644 --- a/proto-google-cloud-datastore-v1/pom.xml +++ b/proto-google-cloud-datastore-v1/pom.xml @@ -4,13 +4,13 @@ 4.0.0 com.google.api.grpc proto-google-cloud-datastore-v1 - 0.105.7-SNAPSHOT + 0.105.7 proto-google-cloud-datastore-v1 PROTO library for proto-google-cloud-datastore-v1 com.google.cloud google-cloud-datastore-parent - 2.14.7-SNAPSHOT + 2.14.7 diff --git a/versions.txt b/versions.txt index 7614b37a6..bd1c2fa3e 100644 --- a/versions.txt +++ b/versions.txt @@ -1,9 +1,9 @@ # Format: # module:released-version:current-version -google-cloud-datastore:2.14.6:2.14.7-SNAPSHOT -google-cloud-datastore-bom:2.14.6:2.14.7-SNAPSHOT -proto-google-cloud-datastore-v1:0.105.6:0.105.7-SNAPSHOT -datastore-v1-proto-client:2.14.6:2.14.7-SNAPSHOT -proto-google-cloud-datastore-admin-v1:2.14.6:2.14.7-SNAPSHOT -grpc-google-cloud-datastore-admin-v1:2.14.6:2.14.7-SNAPSHOT +google-cloud-datastore:2.14.7:2.14.7 +google-cloud-datastore-bom:2.14.7:2.14.7 +proto-google-cloud-datastore-v1:0.105.7:0.105.7 +datastore-v1-proto-client:2.14.7:2.14.7 +proto-google-cloud-datastore-admin-v1:2.14.7:2.14.7 +grpc-google-cloud-datastore-admin-v1:2.14.7:2.14.7