Skip to content
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: Introduce API Key support into ClientBuilderBase #732

Merged
merged 1 commit into from
Jan 20, 2024

Conversation

jskeet
Copy link
Collaborator

@jskeet jskeet commented Oct 25, 2023

The intention is to make it easy for APIs which do support API keys to expose that, without providing misleading properties to other client builders.

@jskeet jskeet requested a review from a team as a code owner October 25, 2023 10:31
@jskeet jskeet added the do not merge Indicates a pull request not ready for merge, due to either quality or timing. label Oct 25, 2023
@jskeet
Copy link
Collaborator Author

jskeet commented Oct 25, 2023

googleapis/google-cloud-dotnet#11217 shows how this would be used.

/// <remarks>
/// This is protected as not all APIs support API keys. APIs which support API keys
/// should declare a new public property (also called ApiKey) in the concrete client builder class,
/// and ensure they call <see cref="GetEffectiveSettings{T}(T)"/> to potentially specify the API key header
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm wondering, why can't we add a default implementation for Build and BuildAsync in here (ClientBuilderBase), instead of generating them. If we do that, then we can call GetEffectiveSettings here in the way we need to.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It needs to be able to call a concrete constructor in the client type, and use a settings type which is concrete (and which we're non-generic in).
But we may be able to reduce it further (in the next major version of GAX, of course).

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah yes, we'd need a new majot version for that, and not really much we can do otherwise. Looks good.

@jskeet
Copy link
Collaborator Author

jskeet commented Nov 8, 2023

A different alternative to consider:

  • Most of the API key support in the base class is as it was before
  • Remove GetEffectiveSettings, but add a protected AdditionalCallSettings property in the base class which normally returns null, but would return any extra call settings, e.g. for an API key or anything else we want
  • Either generate an EffectiveSettings property, or generate an internal static GetEffectiveSettings(XyzSettings settings, CallSettings additionalSettings) method in each concrete settings class.

Generating actual implementation feels nasty, but so does the GetEffectiveSettings method in this PR. Urgh. I'm still thinking about this, basically.

/// <c>GetEffectiveSettings(Settings?.Clone())</c>.</remarks>
/// <typeparam name="T">The concrete settings type, derived from <see cref="ServiceSettingsBase"/>, with a
/// parameterless constructor that can be used to construct a new default instance.</typeparam>
/// <param name="settings">A clone of the existing settings specified in the concrete builder type. May be null.</param>
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've been thinking about this from the perspective of creating clones unnecessarily... and I'm now not that bothered. It's only once per client creation and it's only if the user has specified settings explicitly (which will be pretty rare).

@jskeet
Copy link
Collaborator Author

jskeet commented Nov 9, 2023

I've continued thinking about this, and while the whole "clone the settings" part is a bit annoying, I think it's okay for now. Maybe in the next GAX major version we should make the builder generic in the settings type as well, which would allow us to generate less per-API code, I suspect. Will note that, but for now I'm happy to go with this, and change the generator to unconditionally generate the call to GetEffectiveSettings. (We should look into it for hand-written client builders...)

Thoughts?

@amanda-tarafa
Copy link
Collaborator

amanda-tarafa commented Nov 9, 2023

I've been thinking about this as well and I haven't come up with anything that's clean. A tweak to your alternative solution might be to:

  • Like yours: Add the CallSettings AdditionalCallSettings property on the base client builder and have the base client builder deal with everything API Key related (and other similar ones in the future).
  • On the XYZClient change the generated Create method to accept both XYZSettings and CallSettings additionalCallSettings.
  • Have the XYZClient.Create method calculate the effective XYZSettings by cloning and merging the passed XYZSettings with the additionalCallSettings if necessary.

It's still generating implementation but in a place where we are already generating related implementation, for instance XYZClientImpl's constructor calculates effective settings in case the passed settings are null, so, it's just a little bit more of that.

Otherwise, this is fine as well. I do +1 strongly making the client builder base generic on the settings type on the next major version.

@jskeet
Copy link
Collaborator Author

jskeet commented Nov 10, 2023

I've been wanting to avoid adding a new Create overload - otherwise I completely agree that would be a good call. No huge urgency for this, so I'll keep pondering options.

@jskeet
Copy link
Collaborator Author

jskeet commented Jan 19, 2024

It's been a couple of months now, and I haven't figured out anything better than this. Shall we just go with this? I can't remember offhand how easy it is to write tests for this sort of thing, but I can definitely look into it.

@amanda-tarafa
Copy link
Collaborator

Yep, I'm fine with this approach, I don't think we can do much better.

@jskeet jskeet removed the do not merge Indicates a pull request not ready for merge, due to either quality or timing. label Jan 19, 2024
@jskeet jskeet changed the title (DO NOT MERGE) Prototype of API key support in GAX feat: Introduce API Key support into ClientBuilderBase Jan 19, 2024
The intention is to make it easy for APIs which *do* support API
keys to expose that, without providing misleading properties to
other client builders.
@jskeet
Copy link
Collaborator Author

jskeet commented Jan 19, 2024

This is now ready for review and merging. There are tests for GetEffectiveSettings - a lot of the rest is hard to test due to ADC.

jskeet added a commit to jskeet/gapic-generator-csharp that referenced this pull request Jan 19, 2024
This will allow API key support to be introduced through partial classes.

Requires googleapis/gax-dotnet#732 to be merged and released.
@jskeet jskeet merged commit efb0bdd into googleapis:main Jan 20, 2024
4 checks passed
@jskeet jskeet deleted the api-key-support branch January 20, 2024 06:51
jskeet added a commit to jskeet/gapic-generator-csharp that referenced this pull request Jan 23, 2024
This will allow API key support to be introduced through partial classes.

Requires googleapis/gax-dotnet#732 to be merged and released.
jskeet added a commit to jskeet/gapic-generator-csharp that referenced this pull request Jan 23, 2024
This will allow API key support to be introduced through partial classes.

Requires googleapis/gax-dotnet#732 to be merged and released.
jskeet added a commit to googleapis/gapic-generator-csharp that referenced this pull request Jan 26, 2024
This will allow API key support to be introduced through partial classes.

Requires googleapis/gax-dotnet#732 to be merged and released.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants