4

Request for Comment (RFC): New Major Version of the Google Cloud PHP Client Libr...

 2 years ago
source link: https://github.com/googleapis/google-cloud-php/discussions/5206
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Good news everyone! The PHP team at Google Cloud is rolling out a new major version of the client libraries for Google Cloud, and we want your feedback! This document is a Request for Comment (RFC) on the proposed changes. If you are a current or future user of these libraries, please tell us what you think!

Summary of Major Changes

1. Updates for PHP 7.4

Add type hints and return types for all generated class methods, properties, and constants. Because union types and the mixed keyword are not supported in PHP 7.4, some parameters and return types will be left untyped until Fall 2022 at the earliest, when PHP 8.2 is released and support is dropped for PHP 7.4 (see Targeted PHP Versions below). We have decided to not use named arguments after some deliberation and community involvement.

Breaking Changes

Customers will not experience breaking changes from typehints, but they will not be able to upgrade unless they are using PHP 7.4 or later.

2. Allowing arguments to move from required to optional

Overview

AIP standards allow for required fields on a protobuf message to move to being optional. Our existing GAPIC design utilizes positional parameters to outline required fields on an RPC. This has led to frequent pain points as method signatures will change and break the PHP clients even when API producers follow AIP guidance correctly.
Goal

Allow any RPC request message parameter to move from required to optional, or optional to required, without breaking the PHP client library API.

Proposed Solution

Every RPC will accept their corresponding protobuf Request object explicitly. RPC methods require one argument, the Request object, as required by the AIP for method signature annotations.

use Google\Cloud\Service\ExampleClient;
use Google\Cloud\Service\CreateInstanceRequest;

$projectId = 'my-project-id'; // client option
$name = 'my-new-instance';    // required parameter in "method_signature" annotation
$priority = 1;                // optional request parameter
$retrySettings = [];          // call-time option

$client = new ExampleClient(['projectId' => $projectId]);
$request = (new CreateInstanceRequest())
    ->setName($name)
    ->setPriority($priority);
$instance = $client->createInstance($request, ['retrySettings' => $retrySettings]);

Breaking Changes

Customers will need to update their code to create request objects as arguments.

// before
$instance = $client->createInstance($name, [
    'priority' => $priority,
    'retrySettings' => $retrySettings
]);

// after
use Google\Cloud\Service\CreateInstanceRequest;
$request = (new CreateInstanceRequest())
    ->setName($name)
    ->setPriority($priority);
$instance = $client->createInstance($request, ['retrySettings' => $retrySettings]);

// NOTE: protobuf messages can also be created using an associative array
$request = new CreateInstanceRequest([
    'name'     => $name,
    'priority' => $priority,
]);

3. Request builder classes

Overview

Using Request objects directly solves an internal scaling issue for us, but can make it more difficult for users to be able to quickly draft out the necessary code to deliver an RPC successfully.

Retain the helpful code hints delivered by having a method signature that flattens our required parameters.

Proposed Solution

A RequestBuilder class will be generated when one or more method signature annotations exist on an RPC in a client. The annotations are considered part of the API’s contract and moving them would be breaking. As such, we can use these annotations to reliably guide users towards fields that are required for a given RPC while still allowing the flexibility of accepting the full request message.

service Example {
  rpc CreateInstance(CreateInstanceRequest) returns (CreateInstanceResponse) {
    option (google.api.method_signature) = "name";
  }
}
class ExampleRequestBuilder
{
    public static function createInstanceRequest(string $name): CreateInstanceRequest
}
use Google\Cloud\Service\ExampleClient;
use Google\Cloud\Service\RequestBuilder\ExampleRequestBuilder;

$projectId = 'my-project-id'; // client option
$name = 'my-new-instance';    // required parameter in "method_signature" annotation
$priority = 1;                // optional request parameter
$retrySettings = [];          // call-time option

$client = new ExampleClient(['projectId' => $projectId]);
$request = ExampleRequestBuilder::createInstanceRequest($name)
    ->setPriority($priority);
$instance = $client->createInstance($request, [
    'retrySettings' => $retrySettings
]);

A similar pattern can be found in java’s clients, which use overloads to provide multiple signatures for a given RPC.

Breaking Changes

No breaking changes are involved in this design, as the method signature annotations were previously unsupported. However, these helpers will ease the upgrade process by making it easier to create the requests for each RPC call.

4. Resource name helpers

Overview

Resource name template helpers currently live within each GAPIC. They are generated using resource annotations. Especially for services which have a large surface, this can lead to a large number of additional generated methods within each client. This can make understanding and parsing out the available RPCs in a client marginally more difficult when reading through documentation.

Segregate concerns and allow for more clear documentation.

Proposed Solution

A PathTemplate class will be generated when one or more path templates exist on a client RPC.

service Example {
  rpc GetInstance(GetInstanceRequest) returns (Instance) {
  }
}
message GetInstanceRequest {
  string name = 1 [(google.api.resource_reference).type = "example.googleapis.com/Instance"];
}
message Instance {
  option (google.api.resource) = {
    type: "example.googleapis.com/Instance"
    pattern: "projects/{project}/instances/{instance}"
  };

  string name = 1;
}
class ExamplePathTemplate
{
    public static function instanceName(string $project, string $instance): string
}
use Google\Cloud\Service\ExampleClient;
use Google\Cloud\Service\ResourceNames\ExampleResourceNames;
use Google\Cloud\Service\GetInstanceRequest;

$projectId = 'my-project-id';
$name = 'my-new-instance';

$client = new ExampleClient(['projectId' => $projectId]);
$instanceName = ExampleResourceNames::instanceName($projectId, $name);
$request = (new GetInstanceRequest())
    ->setName($instanceName);
$instance = $client->getInstance($request);

Breaking Changes

Customers will need to update their code to call the resource name helpers from the new classes.

// before
$instanceName = $client->instanceName($projectId, $name);

// after
use Google\Cloud\Service\ResourceNames\ExampleResourceNames;
$instanceName = ExampleResourceNames::instanceName($projectId, $name);

5. Asynchronous support

Overview

Support for asynchronous requests has been wired in, but not yet exposed to users except in specific cases such as StorageObject::downloadAsStreamAsync. Delivering requests asynchronously can offer a large performance boon for users depending on their use case.

Improve user experience and publish asynchronous requests in a way that does not bloat clients with duplicated methods (e.g. commit/commitAsync).

Proposed Solution

Every client will have a sendAsync method, which takes the name of the method and the Request object, and returns a Promise. Creating the request will look no different than when making a synchronous call, but the function called (sendAsync) and returned object (Promise) will change.

$promise = $client->sendAsync('createInstance', $request, [
    'retrySettings' => $retrySettings
]);
$instance = $promise->wait();

This method lacks the strong typing of the other methods, but the $request type will be validated using the method name, and throw an exception if invalid.

Breaking Changes

No breaking changes are involved in this design, as asynchronous calls were previously unsupported.

6. Changes to Handwritten Clients and Core

Our "handwritten" libraries, or libraries which have large parts written outside the client generator, such as BigQuery, Datastore, PubSub, and Spanner, are bespoke and require a separate RFC to cover their specific changes in detail. In summary, divergent logic between GAPIC and handwritten client libraries will be consolidated. This logic includes but is not limited to:

  • Client constructor options - Handwritten client options will be renamed or refactored to be consistent with GAPIC client options.
  • Handwritten Connection classes - Handwritten clients will wrap GAPICs or use the GAX transport layer so the connection classes can be removed.
  • Handwritten Exception classes - Google Cloud Core contains Exception wrapper classes for GAX for client libraries which do not use GAX. REST and gRPC exceptions do not use the same exceptions.

Breaking Changes

For handwritten libraries there will be breaking changes with how our customers will catch exceptions and pass in client options for Handwritten clients. These will be discussed in the separate PRD.

Rollout and Support

Targeted PHP Versions

See: Supported PHP versions

PHP will support at least 3 major versions going forward, and the libraries will always be compatible with at least one GA runtime for App Engine and Cloud Functions. As PHP has a release candidate of a major version every year, this means always supporting the last 2-3 years of PHP versions.

Target Versions:

  • PHP 8.1
  • PHP 8.0
  • PHP 7.4

The next major version of Google Cloud PHP client libraries is targeting PHP 7.4 as a minimum version and will not be compatible with PHP 7.3 and below.

Rollout

New clients will be created using a new version of the client generator (v2). All cloud client libraries created using the v2 generator will receive a new release containing all breaking changes at the same time. This ensures customers can update all their client libraries together. Users will not be able to install a version of a client library created using the v2 generator in the same project as a version of a client library created using the v1 generator, as this would cause a dependency conflict. Documentation for the new clients will be deployed to https://cloud.google.com/php/docs.

Support

Previous versions of clients created using the v1 generator will receive security patches only.

Conclusion

We hope this next major version of the client libraries improves the experience of all our users and introduces useful language and library features. If you feel anything could be improved or changed in this proposal, please voice your thoughts here! Thank you!

Sincerely,
The Google Cloud PHP team


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK