-
Notifications
You must be signed in to change notification settings - Fork 358
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 leader routing #11654
feat: Spanner leader routing #11654
Conversation
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.
What's there looks fine, but I'm slightly surprised there isn't connection string support. Is the idea that this would be disabled so rarely that we don't need to make it easy? (I can't remember exactly how SpannerConnection construction works - is there a way of passing in arbitrary settings?)
apis/Google.Cloud.Spanner.V1/Google.Cloud.Spanner.V1/SpannerClientPartial.cs
Show resolved
Hide resolved
using System; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
|
||
namespace Google.Cloud.Spanner.V1 | ||
{ | ||
public partial class SpannerClientBuilder | ||
{ | ||
public partial class SpannerClientBuilder |
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.
There are some weird changes to indentation in this 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.
Uhh, yes, fixing
@@ -76,5 +87,17 @@ public SpannerClientBuilder MaybeCreateEmulatorClientBuilder() | |||
builder.CopySettingsForEmulator(this); | |||
return builder; | |||
} | |||
|
|||
internal new T GetEffectiveSettings<T>(T settings) where T : ServiceSettingsBase, new() |
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.
Humbug - I guess we should have made the method virtual in GAX? Not that it's a problem, so long as we don't call it from GAX.
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, I did add this to the next major version things to consider.
{ | ||
if (Settings.LeaderRoutingEnabled) | ||
{ | ||
settings = settings.WithHeader(LeaderRoutingHeader, true.ToString()); |
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 think it would be clearer to put the constant in here, rather than calling true.ToString()
. (It will also return "True" - I'd expect "true" to be more idiomatic, although I'm not sure the value actually matters.)
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 using the constant. Value matters and the specified value on desing is "True". The header set to False, unset or not present are all equivalent and mean "do not route to leader".
/// some operations will never be explicitly routed to the leader, and some operations will | ||
/// be routed to the leader depending on the transaction type they are using. | ||
/// </remarks> | ||
internal bool LeaderRoutingEnabled { get; set; } = true; |
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'm slightly surprised this is internal rather than public. Is there a reason for that?
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.
Yes, because this is just how we trickle this setting down to the client where we actually use it. It's not how this setting is exposed for configuration to the user, that is done through the SpannerClientBuilder for users using Spanner.V1 and the connection string for users using Spanner.Data.
If we make it public here and users also can set it, then we'd have to react to users providing different values in the pairs SpannerClientBuilder.LeaderRoutingEnabled + SpannerSettings.LeaderRoutingEnabled and ConnectionString.LeaderRoutingEnabled + SpannerSettings.LeaderRoutingEnabled. An alternative to avoiding that is removing the setting from SpannerClientBuilder and ConnectionString and make it only available through SpannerSettings. That wouldn't be a huge deal for Spanner.V1 users, they'd just have to set a SpannerClientBuilder.SpannerSettings = new SpannerSettings { LeaderRoutingEnabled = false; }
but it would be worse for Spanner.Data users as they wouldn't be able to use the default SessionPoolManager, they'd had to build one themselves to be able to pass custom SpannerSettings.
Does this makes sense? The last commit is now the connection string bit, so happy to chat more about this.
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.
Yup, that's fine.
14100f6
to
2b77148
Compare
@@ -146,7 +146,11 @@ public void SetsHeaderOnBeginTransaction() | |||
{ | |||
var invoker = new FakeCallInvoker(); | |||
var client = new SpannerClientBuilder { CallInvoker = invoker }.Build(); | |||
client.BeginTransaction(new BeginTransactionRequest { Session = SampleSessionName }); | |||
client.BeginTransaction(new BeginTransactionRequest |
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.
Rather than change the test, perhaps we should fix the code so that it doesn't fail with an NRE? (If it definitely would be an invalid request, we could potentially throw an ArgumentException, but to be honest I think it would be better to just default to a particular mode and let the server reject it.)
I suspect it's just a case of using request.Options?.ModeCase ?? TransactionOptions.ModeOneofCase.None
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.
Yes, of course! Fixing.
2b77148
to
268ac12
Compare
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.
@jskeet all review comments addressed in new ordered commits prefixed "Address review". Plus a new commit at the end adding connection string support (I was waiting for confirmation this was wanted).
apis/Google.Cloud.Spanner.V1/Google.Cloud.Spanner.V1/SpannerClientPartial.cs
Show resolved
Hide resolved
using System; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
|
||
namespace Google.Cloud.Spanner.V1 | ||
{ | ||
public partial class SpannerClientBuilder | ||
{ | ||
public partial class SpannerClientBuilder |
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.
Uhh, yes, fixing
@@ -76,5 +87,17 @@ public SpannerClientBuilder MaybeCreateEmulatorClientBuilder() | |||
builder.CopySettingsForEmulator(this); | |||
return builder; | |||
} | |||
|
|||
internal new T GetEffectiveSettings<T>(T settings) where T : ServiceSettingsBase, new() |
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, I did add this to the next major version things to consider.
{ | ||
if (Settings.LeaderRoutingEnabled) | ||
{ | ||
settings = settings.WithHeader(LeaderRoutingHeader, true.ToString()); |
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 using the constant. Value matters and the specified value on desing is "True". The header set to False, unset or not present are all equivalent and mean "do not route to leader".
/// some operations will never be explicitly routed to the leader, and some operations will | ||
/// be routed to the leader depending on the transaction type they are using. | ||
/// </remarks> | ||
internal bool LeaderRoutingEnabled { get; set; } = true; |
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.
Yes, because this is just how we trickle this setting down to the client where we actually use it. It's not how this setting is exposed for configuration to the user, that is done through the SpannerClientBuilder for users using Spanner.V1 and the connection string for users using Spanner.Data.
If we make it public here and users also can set it, then we'd have to react to users providing different values in the pairs SpannerClientBuilder.LeaderRoutingEnabled + SpannerSettings.LeaderRoutingEnabled and ConnectionString.LeaderRoutingEnabled + SpannerSettings.LeaderRoutingEnabled. An alternative to avoiding that is removing the setting from SpannerClientBuilder and ConnectionString and make it only available through SpannerSettings. That wouldn't be a huge deal for Spanner.V1 users, they'd just have to set a SpannerClientBuilder.SpannerSettings = new SpannerSettings { LeaderRoutingEnabled = false; }
but it would be worse for Spanner.Data users as they wouldn't be able to use the default SessionPoolManager, they'd had to build one themselves to be able to pass custom SpannerSettings.
Does this makes sense? The last commit is now the connection string bit, so happy to chat more about this.
@@ -146,7 +146,11 @@ public void SetsHeaderOnBeginTransaction() | |||
{ | |||
var invoker = new FakeCallInvoker(); | |||
var client = new SpannerClientBuilder { CallInvoker = invoker }.Build(); | |||
client.BeginTransaction(new BeginTransactionRequest { Session = SampleSessionName }); | |||
client.BeginTransaction(new BeginTransactionRequest |
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.
Yes, of course! Fixing.
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.
Just one simple change requested, but I think it's an important one (or I've misunderstood something).
apis/Google.Cloud.Spanner.V1/Google.Cloud.Spanner.V1/SpannerClientPartial.cs
Show resolved
Hide resolved
@@ -436,6 +437,20 @@ public EmulatorDetection EmulatorDetection | |||
} | |||
} | |||
|
|||
/// <summary> | |||
/// Options to control leader routing. This is true by 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.
I don't think this is true by default, and we don't have a test for it.
I suspect the change is just to call GetValueOrDefault(EnableLeaderRoutingKeyword, "True")
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.
Yes! thanks for catching this. I'll add a test as well.
/// some operations will never be explicitly routed to the leader, and some operations will | ||
/// be routed to the leader depending on the transaction type they are using. | ||
/// </remarks> | ||
internal bool LeaderRoutingEnabled { get; set; } = true; |
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.
Yup, that's fine.
268ac12
to
070d09a
Compare
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.
@jskeet all previous commits squashed into one plus a new commit fixing the leader routing default in the connection string (I'll squash that one as well before mergin.) PTAL.
070d09a
to
cd5419c
Compare
@jskeet as always one commit at a time. Although most of these will be squashed in a single commit for merging.