-
Notifications
You must be signed in to change notification settings - Fork 318
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: add support for Firestore database id configuration #2164
Conversation
...java/com/google/cloud/spring/autoconfigure/firestore/GcpFirestoreAutoConfigurationTests.java
Show resolved
Hide resolved
@diegomarquezp I found the error message your pull request should fix "Caused by: java.sql.SQLException: Access denied for user 'root'@'cloudsqlproxy~20.49.35.21' (using password: YES)" |
...main/java/com/google/cloud/spring/autoconfigure/firestore/GcpFirestoreAutoConfiguration.java
Outdated
Show resolved
Hide resolved
...re/src/main/java/com/google/cloud/spring/autoconfigure/firestore/GcpFirestoreProperties.java
Outdated
Show resolved
Hide resolved
...java/com/google/cloud/spring/autoconfigure/firestore/GcpFirestoreAutoConfigurationTests.java
Outdated
Show resolved
Hide resolved
@blakeli0 Do I need a newer version of GAX or Firestore client lib? |
Iirc, Firestore temporarily removed code for gRPC's Dynamic Routing Headers a while back (due to an encoding issue). I think they only recently added that back in: googleapis/java-firestore#1418. I think this would work with Firestore v3.14.3+ (I have no idea how the tests work and it could be a different issue). |
As Lawrence mentioned, they recently added the routing headers back and Spring Cloud GCP didn't get it yet. But if this is the root cause, it means that the server made a behavior breaking change that requires the customers to update their client code, which is very bad. |
.withCallCredentials( | ||
MoreCallCredentials.from( | ||
GcpFirestoreAutoConfiguration.this.credentialsProvider.getCredentials())); | ||
|
||
// add routing header for custom database id | ||
if (databaseId != null && !databaseId.equals("(default)")) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Routing header should be passed in all requests. It just happens it is only enforced on non-default database ids.
The projectId and databaseId should be URL encoded. Basically, treat this string the same as you would treat query part of a URL.
Ask Sichen Liu if you need more details. There is a performance impact if you omit header for default database (I believe).
Metadata routingHeader = new Metadata(); | ||
Metadata.Key<String> key = | ||
Metadata.Key.of(Headers.DYNAMIC_ROUTING_HEADER_KEY, Metadata.ASCII_STRING_MARSHALLER); | ||
routingHeader.put(key, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This may work for this specific case, but routing header config could change in the future. I'm not sure it works for all the new routing header configs either, but maybe those are not required.
In long term, switching to GAPIC stubs should solve this issue, but I'm not sure it is compatible with the Reactive paradigm. Why did we choose to use the gRPC generated stubs instead of GAPIC ones? Only because of Reactive?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, this integration was specifically made to support reactive, and I believe at the time GAPIC was not compatible.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see. My concern is that every time the backend makes the routing header required for a new RPC, or change how the routing header is constructed, we would have to come back and manually change it in spring-cloud-gcp. It may not in scope of this PR, can we investigate the possibility of switching to the GAPIC stubs?
Metadata.Key<String> key = | ||
Metadata.Key.of(Headers.DYNAMIC_ROUTING_HEADER_KEY, Metadata.ASCII_STRING_MARSHALLER); | ||
routingHeader.put(key, | ||
"project_id=" + URLEncoder.encode(projectId, StandardCharsets.US_ASCII) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We use PercentEscaper in gax, which I think has slight advantage over the Java default one based on @lqiu96's investigation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Switch to `PercentEscaper1.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
Kudos, SonarCloud Quality Gate passed! |
@@ -68,7 +68,7 @@ The following configuration options are available: | |||
| Name | Description | Required | Default value | |||
| `spring.cloud.gcp.datastore.enabled` | Enables the Cloud Datastore client | No | `true` | |||
| `spring.cloud.gcp.datastore.project-id` | Google Cloud project ID where the Google Cloud Datastore API is hosted, if different from the one in the <<spring-cloud-gcp-core,Spring Framework on Google Cloud Core Module>> | No | | |||
| `spring.cloud.gcp.datastore.database-id` | Google Cloud project can host multiple databases. You can specify which database will be used. | No | | |||
| `spring.cloud.gcp.datastore.database-id` | Google Cloud project can host multiple databases. You can specify which database will be used. If not specified, the database id will be "(default)". | No | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"Default value" column is missing.
Also adds routing headers for all Firestore requests. Fixes #2145.
Hi @meltsufin, this breaks my (test) configuration where I only define service credentials via spring.cloud.gcp.firestore.credentials.encoded-key - this contains the project ID, and somehow this worked till 4.7.2, but crashes here, as the percent escaper receives projectId null. Do you have an idea how this should work? |
@thoastbrot I guess it's because your project ID is |
I'll do that. dummy project-id doesn't work the way you assume. |
With feature in [#2164](#2164), now Firestore can run in same project as datastore. This PR cleans up settings for integration tests ci so that tests for Firestore module and samples run in the same ci project as the rest. Modules affected in this change: - autoconfigure/firestore - data-firestore - data-firestore-sample - starter-firestore-sample Before this change, these modules are setup to run with `spring-cloud-gcp-ci-firestore` project. After this change: - database-id=firestoredb is specified for above module's tests. - does not specify `firestore.project-id` and get project id info from `DefaultGcpProjectIdProvider`. For integration test ci, it is `spring-cloud-gcp-ci` set via gcloud [here](https://github.com/GoogleCloudPlatform/spring-cloud-gcp/blob/ef30225e60e270f8cc1a9213728f0cfdd7e4de50/.github/workflows/integrationTests.yaml#L51).
Fixes #2145.