-
Notifications
You must be signed in to change notification settings - Fork 362
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: spanner emulator support #4915
Conversation
skuruppu
commented
Apr 29, 2020
•
edited
Loading
edited
- Allows users to set EmulatorDetection through SpannerConnectionStringBuilder.
- Configures integration tests with EmulatorDetection.EmulatorOrProduction.
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.
Same comments will apply for all three - but yes, this looks it's the the right starting point. Once this is in place, I'm hoping the Spanner.Data integration should be straightforward.
...ud.Spanner.Admin.Database.V1/Google.Cloud.Spanner.Admin.Database.V1/DatabaseAdminClient.g.cs
Outdated
Show resolved
Hide resolved
...anner.Admin.Database.V1/Google.Cloud.Spanner.Admin.Database.V1/DatabaseAdminClientBuilder.cs
Outdated
Show resolved
Hide resolved
@jskeet this is now ready for review. I ran the ITs and they ran for the most part: Total tests: 167 I will go through the failed tests to figure out which ones need to be skipped (due to the emulator not supporting all features that the production backend supports). This will need to be done in a separate PR. If there's anything that can be fixed in terms of the setup, I will do so in this PR. |
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 suggest we split this PR in half: let's get the easy bits (the three underlying API clients) done first, then look at how we configure it from Spanner.Data as a separate PR.
But fundamentally I'd really like SpannerConnectionStringBuilder and SpannerClientCreationOptions to do the bulk of the work here.
apis/Google.Cloud.Spanner.Data/Google.Cloud.Spanner.Data/SessionPoolManager.cs
Outdated
Show resolved
Hide resolved
@@ -313,7 +323,8 @@ private static async Task<SpannerClient> CreateClientAsync(SpannerClientCreation | |||
return new SpannerClientBuilder | |||
{ | |||
CallInvoker = callInvoker, | |||
Settings = spannerSettings | |||
Settings = spannerSettings, | |||
EmulatorDetection = emulatorDetection |
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.
Setting a call invoker and emulator detection would be an odd thing to do. (I'm slightly surprised we don't prohibit it.)
If we do the work in SpannerClientCreationOptions (which may mean some code duplication, unfortunately - let's see what we can do) the endpoint and credentials will already be set correctly, so we shouldn't need to make any changes here.
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.
Oh I see, so we shouldn't rely on the automated emulator detection for the data client. We should only do that for the admin clients. So we'll manually read the env var and set the endpoint and credentials. Is the worry that it would confuse users because they would set an endpoint and credentials but we'd be using a different parameters for the actual connection?
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.
It's not a matter of "not relying" on the automated emulation code - it's not that we don't trust it. It's a matter of making it fit in well with the rest of the infrastructure.
I'd like to investigate how to do this without code duplication though - for example, it may be possible to add a public member to SpannerClientBuilder
to say "please let me know how you would be configured for emulation" (effectively like the current partial method does) and then use the endpoint and credentials from that.
I think our aim should be for the behavior to be consistent between "using SpannerClientBuilder directly" and "using SpannerConnectionStringBuilder directly" in terms of the connection.
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've made the minimal amount of changes to get this working. But I'm still not updating the endpoint and credentials in the connection string to reflect what is actually being connected to. I think this is where your comment regarding updating the SpannerClientBuilder
comes in.
The other issue that I want to solve is that if the connection string has EmulatorDetection then users shouldn't be asked to specify credentials. I'll also work on trying to bypass this check.
apis/Google.Cloud.Spanner.Data/Google.Cloud.Spanner.Data/SpannerConnectionStringBuilder.cs
Outdated
Show resolved
Hide resolved
Thanks @jskeet. I agree about doing this as two separate PRs. To preserve the discussion, I may leave this PR as is to continue the work on setting the connection properties. I'll cherry-pick the builders into a separate PR. |
I've merged #4928 now, so it's probably worth rebasing this PR, unless you'd prefer to start a new one. |
8cef6dd
to
0968dd4
Compare
I'll get to this when I can, but it may go into next week I'm afraid. |
No worries @jskeet. I'm also sporadically working on it when I find bits of time here and there. |
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 is moving in the right direction, but I think we probably need to move the CallInvoker creation from SessionPoolManager into SpannerClientCreationOptions. We may need to add something to SpannerClientBuilder to make it easier to say "What endpoint and credentials would you use for this?" without actually performing the build afterwards.
It's tricky for me to speculate on exactly what's required without basically doing it myself, unfortunately. Let me know how you'd like us to proceed.
apis/Google.Cloud.Spanner.Data/Google.Cloud.Spanner.Data/SpannerConnectionStringBuilder.cs
Outdated
Show resolved
Hide resolved
b4da2fa
to
e98b470
Compare
This is what I came up with for now e98b470. I don't think you need to move the CallInvoker to SpannerClientCreationOptions, as long as the endpoint and credentials can be correctly extracted from that class. My proposed change to SpannerClientBuilder is a bit of a mess since there's no nice way to extract the endpoint and credentials without attempting to build an instance of the class. For now I'm reading the env var manually. But if there was a static version of Sorry, I know the back-and-forth is taking a bit of time. I'm more than happy for you to take a crack at this but I know you have a lot more stuff going on so I want to help as much as possible. |
Building an instance of I would suggest just making |
e98b470
to
0ce5165
Compare
PTAL @jskeet. I made all the discussed changes. |
apis/Google.Cloud.Spanner.Data/Google.Cloud.Spanner.Data/SpannerClientCreationOptions.cs
Outdated
Show resolved
Hide resolved
Will have a look when I get a chance, but it may well be quite late in the week. |
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.
Getting a lot closer - but the session pool options bother me. Do you want me to see if I can figure out a way that we can make the options "just work"?
apis/Google.Cloud.Spanner.V1/Google.Cloud.Spanner.V1/SpannerClientBuilder.cs
Outdated
Show resolved
Hide resolved
apis/Google.Cloud.Spanner.V1/Google.Cloud.Spanner.V1/SpannerClientBuilder.cs
Outdated
Show resolved
Hide resolved
apis/Google.Cloud.Spanner.Data/Google.Cloud.Spanner.Data/SpannerClientCreationOptions.cs
Outdated
Show resolved
Hide resolved
}; | ||
var emulatorBuilder = clientBuilder.MaybeCreateEmulatorClientBuilder(); |
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 wonder whether this should be in the production code, if everyone will always need to do that.
Do we know whether this is a long-term restriction?
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.
In general, the changes in this file (beyond just setting EmulatorDetection) feel like they're a symptom of us not doing quite enough to "just make it work".
ConnectionString = databaseBuilder.ConnectionString; | ||
DatabaseName = databaseBuilder.DatabaseName; | ||
Builder = builder.WithDatabase(SpannerDatabase); | ||
Builder.EmulatorDetection = emulatorDetection; |
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 shouldn't need to set the EmulatorDetection again, should we?
@@ -116,6 +143,6 @@ private static string GetEnvironmentVariableOrDefault(string name, string defaul | |||
return string.IsNullOrEmpty(value) ? defaultValue : value; | |||
} | |||
|
|||
public SpannerConnection GetConnection() => new SpannerConnection(ConnectionString); | |||
public SpannerConnection GetConnection() => new SpannerConnection(Builder); |
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.
Why is this change required? I'd expect the connection string to be fine.
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.
Or is this because we've set the SessionPoolManager because of the options? It feels like a lot of this change could go away if we didn't need to set the options explicitly.
This reverts commit ccbc10d.
c77186d
to
d367870
Compare
I addressed most of the changes except for the ones in https://github.com/googleapis/google-cloud-dotnet/pull/4915/files#diff-450b4cc43d8fb620f621d63b7de37a31 relating to the session pool. For context, the changes to that file came out of #4970 when I was trying to run the existing ITs against the emulator. To be honest, I haven't quite gotten the whole thing to work yet even with that change. My preference would be to revert the changes to that file and work on it separately. The highest priority is to add the emulator support to the client since there is a customer that's keen to try this out in C#. Getting the ITs to work is a bonus so that we can report emulator issues to the dev team and perhaps have a presubmit that runs the ITs against the emulator. But this will require a bunch of work from my side and from the emulator team to fix some of the failing tests. @jskeet I would be happy for you to try out a fix for the session pool issue. I'm not familiar with it enough to know what to change. But only if you have time. Otherwise, I'll work on it until I figure it out. I don't know if the emulator team is planning to fix the concurrent transaction issue before GA. I will check with them and get back to you. Let me know if you're ok with me reverting changes to that file. |
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 agree that we should revert the integration test change - and the rest now looks good to me. I can try the integration test piece early next week, I expect, but we could get this in before then and do a beta release. The customer would need to configure the session pool options themselves in that beta release, but we can hope to either do it for them in a later release, or not need to do it at all if the emulator changes.
apis/Google.Cloud.Spanner.V1/Google.Cloud.Spanner.V1/SpannerClientBuilder.cs
Outdated
Show resolved
Hide resolved
This reverts commit 677ae2f.
All done, thanks for the review feedback @jskeet. |
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.
Thanks - will squash and merge, then look into the SessionPoolOptions aspect.