diff --git a/aip/client-libraries/4234.md b/aip/client-libraries/4234.md new file mode 100644 index 000000000..c356e7c15 --- /dev/null +++ b/aip/client-libraries/4234.md @@ -0,0 +1,135 @@ +--- +id: 4234 +state: reviewing +created: 2021-06-07 +--- + +# Common service client mixins + +Often, APIs can have common features for administering resources that are +separated into utility services. These common, utility services are shared among +the discrete product services. These common services each have a +centrally-defined surface, but individual instances are hosted alongside each +product service. Thus, the surfaces of each common service hosted by the product +service are "mixed in" at runtime. + + +## Guidance + +Client libraries **may** provide client methods for the common services that its +API declares to be mixed-in. Such methods improve the user experience by +presenting the mixin methods from a client configured to communicate with the +product service that hosts the mixin service. + +If client libraries support mixin services, they **must** support the following +common services (and **may** support others): + +- `google.cloud.location.Locations` +- `google.iam.v1.IAMPolicy` +- `google.longrunning.Operations` + +**Note:** The list of supported mixin services and the mixin services +themselves both change infrequently. Any new common service to be supported +**must** be added to the list here and generators **must** be updated. + +To be generated into a client library, a mixin service **must** be declared +under [apis] in a [google.api.Service]. Furthermore, only the RPCs with +[google.api.http] bindings declared in the [http] configuration of the same +[google.api.Service] can be generated (more details on these bindings in +AIP-127). If a mixin service RPC does not have a [google.api.http] rule declared +in the [google.api.Service], it **must not** be generated. + + +## Implementing mixin support + +### Generator configuration + +Client library generators **must** accept the file path of a +[google.api.Service] in YAML form. This file is specified via a flag that +**must** be optional. In other words, the flag **must not** be required for +basic client generation that omits the mixin methods. + +### Mixin API client configuration + +If a mixin API utilizes client library configuration (i.e. annotations, default +retry settings, etc.) such as `google.api.method_signature` or request header +injection, generators **may** support it in the generated mixin methods if the +configuration is accessible. + +Where client library configuration calls for a fully-qualified name, the +_mixin's_ fully-qualified name **must** be used. That is to say, the host +service **must not** refer to a mixin element as if it was in its own package. + +For example, configuring `google.iam.v1.IAMPolicy.GetIAMPolicy` with default +retry and timeout settings would be as follows: + +```json +{ + "name": [{ "service": "google.iam.v1.IAMPolicy", "method": "GetIAMPolicy" }], + "timeout": "60s", + "retryPolicy": { + "initialBackoff": "0.1s", + "maxBackoff": "5s", + "backoffMultiplier": 1.3, + "retryableStatusCodes": ["UNKNOWN"] + } +} +``` + +### Generating mixin methods + +The mixin API RPCs **should** be generated as methods on the surface of the +host API's service client library, alongside the host service's RPCs. This +presents them as top-level methods on the client, but under-the-hood, the +appropriate mixin API stub or request should be invoked. However, generators +**may** choose to present the mixin API RPCs in a different manner if it is more +language idiomatic. + +**Note:** For gRPC clients, the mixin API gRPC stub **must** be used in order +to properly construct the gRPC request. For example, the generated, Go gRPC stub +[LocationsClient] must be used to invoke RPCs for the +`google.cloud.location.Locations` mixin, as opposed to that of the host +service's gRPC stub. + +### Multiple host service clients + +If there are multiple services defined by the host API that would result in +multiple clients being generated, generators **must** include the mixin +methods on all eligible, generated service clients. + +### Overriding a duplicate RPC + +Client library generators **must not** generate a mixin method on any host +service client if a host service already defines an RPC with the same name. For +example, take the following service definition: + +```proto +service LibraryService { + rpc ListBooks(ListBookRequest) returns (ListBooksResponse); + + // Other host API RPCs... + + // Redefinitions of the google.iam.v1.IAMPolicy mixin service. + rpc GetIamPolicy(google.iam.v1.GetIamPolicyRequest) + returns (google.iam.v1.Policy); + + rpc SetIamPolicy(google.iam.v1.SetIamPolicyRequest) + returns (google.iam.v1.Policy); + + rpc TestIamPermissions(google.iam.v1.TestIamPermissionsRequest) + returns (google.iam.v1.TestIamPermissionsResponse); +} +``` + +Should the host API declare the `google.iam.v1.IAMPolicy` as a mixin service, +client library generators **must not** generate the resulting mixin methods that +match the names explicitly declared above for _any_ service client in the host +proto package, but they **must** generate the other methods for this mixin. In +this case, the generator **may** log a warning indicating that a collision was +avoided, or silently skip the mixin methods in question. + +[apis]: https://github.com/googleapis/googleapis/blob/master/google/api/service.proto#L96 +[google.api.Service]: https://github.com/googleapis/googleapis/blob/master/google/api/service.proto +[google.api.Http]: https://github.com/googleapis/googleapis/blob/master/google/api/http.proto +[http]: https://github.com/googleapis/googleapis/blob/master/google/api/service.proto#L124 +[LocationsClient]: https://pkg.go.dev/google.golang.org/genproto@v0.0.0-20210325141258-5636347f2b14/googleapis/cloud/location#LocationsClient