diff --git a/Sources/GRPCProtobuf/Documentation.docc/Articles/API-stability-of-generated-code.md b/Sources/GRPCProtobuf/Documentation.docc/Articles/API-stability-of-generated-code.md new file mode 100644 index 0000000..17c0e82 --- /dev/null +++ b/Sources/GRPCProtobuf/Documentation.docc/Articles/API-stability-of-generated-code.md @@ -0,0 +1,78 @@ +# API stability of generated code + +Understand the impact of changes you make to your Protocol Buffers files on the +generated Swift code. + +## Overview + +The API of the generated code depends on three factors: + +- The contents of the source `.proto` file. +- The options you use when generating the code. +- The code generator (the `protoc-gen-grpc-swift` plugin for `protoc`). + +While this document applies specifically to the gRPC code generated and *not* +code for messages used as inputs and outputs of each method, the concepts still +broadly apply. + +Some of the concepts used in this document are described in more detail in +. + +## The source .proto file + +The source `.proto` file defines the API of your service. You'll likely provide +it to users so that they can generate clients from it. In order to maintain API +stability for your service and for clients you must adhere to the following +rules: + +1. You mustn't change the `package` the service is defined in. +2. You mustn't change or add the `swift_prefix` option. +3. You mustn't remove or change the name of any services in your `.proto` file. +4. You mustn't remove or change the name of any RPCs in your `.proto` file. +5. You mustn't change the message types used by any RPCs in your `.proto` file. + +Failure to follow these will result in changes in the generated code which can +result in build failures for users. + +Whilst this sounds restrictive you may do the following: + +1. You may add a new RPC to an existing service in your `.proto` file. +2. You may add a new service to your `.proto` file (however it is recommended + that you define a single service per `.proto` file). + +## The options you use for generating code + +Code you generate into your Swift Package becomes part of the API of your +package. You must therefore ensure that downstream users of your package aren't +impacted by the options you use when generating code. + +By default code is generated at the `internal` access level and therefore not +part of the public API. You must explicitly opt in to generating code at the +`public` access level. If you do this then you must be aware that changing what +is generated (clients, servers) affects the public API, as does the access level +of the generated code. + +If you need to validate whether your API has changed you can use tools like +Swift Package Manager's API breakage diagnostic (`swift package +diagnose-api-breaking-changes`.) In general you should prefer providing users +with the service's `.proto` file so that they can generate clients, or provide a +library which wraps the client to hide the API of the generated code. + +## The code generator + +The gRPC Swift maintainers may need to evolve the generated code over time. This +will be done in a source-compatible way. + +If APIs are no longer suitable then they may be deprecated in favour of new +ones. Within a major version of the package existing API won't be removed +and deprecated APIs will continue to function. + +If the generator introduces new ways to generate code which are incompatible +with the previously generated code then they will require explicit opt-in via an +option. + +As gRPC Swift is developed the generated code may need to rely on newer +functionality from its runtime counterparts (`GRPCCore` and `GRPCProtobuf`). +This means that you should use the versions of `protoc-gen-grpc-swift` and +`protoc-gen-swift` resolved with your package rather than getting them from an +out-of-band (such as `homebrew`). diff --git a/Sources/GRPCProtobuf/Documentation.docc/Articles/Understanding-the-generated-code.md b/Sources/GRPCProtobuf/Documentation.docc/Articles/Understanding-the-generated-code.md new file mode 100644 index 0000000..ae7dc59 --- /dev/null +++ b/Sources/GRPCProtobuf/Documentation.docc/Articles/Understanding-the-generated-code.md @@ -0,0 +1,143 @@ +# Understanding the generated code + +Understand what code is generated by `protoc-gen-grpc-swift` from a `.proto` +file and how to use it. + +## Overview + +The gRPC Swift Protobuf package provides a plugin to the Protocol Buffers +Compiler (`protoc`) called `protoc-gen-grpc-swift`. The plugin is responsible +for generating the gRPC specific code for services defined in a `.proto` file. + +### Package namespace + +Most `.proto` files contain a `package` directive near the start of the file +describing the namespace it belongs to. Here's an example: + +```proto +package foo.bar.v1; +``` + +The package name "foo.bar.v1" is important as it is used as a prefix for +generated types. The default behaviour is to replace periods with underscores +and to capitalize each word and add a trailing underscore. For this package the +prefix is "Foo\_Bar\_V1\_". If you don't declare a package then the prefix will be +the empty string. + +You can override the prefix by setting the `swift_prefix` option: + +```proto +option swift_prefix = "FooBarV1"; + +package foo.bar.v1; +``` + +The prefix for types in this file would be "FooBarV1" instead of "Foo\_Bar\_V1\_". + +### Service namespace + +For each service declared in your `.proto` file, gRPC will generate a caseless +`enum` which is a namespace holding the generated protocols and types. The name +of this `enum` is `{PREFIX}{SERVICE}` where `{PREFIX}` is as described in the +previous section and `{SERVICE}` is the name of the service as declared in the +`.proto` file. + +As an example the following definition creates a service namespace `enum` called +`Foo_Bar_V1_BazService` (the `{PREFIX}` is "Foo_Bar_V1_" and `{SERVICE}` is +"BazService"): + +```proto +package foo.bar.v1; + +service BazService { + // ... +} +``` + +Code generated for each service falls into three categories: + +1. Service metadata, +2. Service code, and +3. Client code. + +#### Service metadata + +gRPC generates metadata for each service including a descriptor identifying the +fully qualified name of the service and information about each method in the +service. You likely won't need to interact directly with this information but +it's available should you need to. + +#### Service code + +Within a service namespace gRPC generates three service protocols: + +1. `StreamingServiceProtocol`, +2. `ServiceProtocol`, and +3. `SimpleServiceProtocol`. + +The full name of each protocol includes the service namespace. + +> Example: +> +> For the `BazService` in the `foo.bar.v1` package the protocols would be: +> +> - `Foo_Bar_V1_BazService.StreamingServiceProtocol`, +> - `Foo_Bar_V1_BazService.ServiceProtocol`, and +> - `Foo_Bar_V1_BazService.SimpleServiceProtocol`. + +Each of these protocols mirror the `service` defined in your `.proto` file with +one requirement per RPC. To implement your service you must implement one of +these protocols. + +The protocols form a hierarchy with `StreamingServiceProtocol` at the bottom and +`SimpleServiceProtocol` at the top. `ServiceProtocol` refines +`StreamingServiceProtocol`, and `SimpleServiceProtocol` refines +`ServiceProtocol` (and `StreamingServiceProtocol` in turn). + +The `StreamingServiceProtocol` implements each RPC as if it were a bidirectional +streaming RPC. This gives you the most flexibility at the cost of a harder to +implement API. It also puts the responsibility on you to ensure that each RPC +sends and receives the correct number of messages. + +The `ServiceProtocol` enforces that the correct number of messages are sent and +received via its API. It also allows you to read request metadata and send both +initial and trailing metadata. The request and response types for these +requirements are in terms of `ServerRequest` and `ServerResponse`. + +The `SimpleServiceProtocol` also enforces the correct number of messages are +sent and received via its API. However, it isn't defined in terms of +`ServerRequest` or `ServerResponse` so it doesn't allow you access metadata. +This limitation allows it to have the simplest API and is preferred if you don't +need access to metadata. + +| Protocol | Enforces number of messages | Access to metadata +|----------------------------|-----------------------------|------------------- +| `StreamingServiceProtocol` | ✗ | ✓ +| `ServiceProtocol` | ✓ | ✓ +| `SimpleServiceProtocol` | ✓ | ✗ + +#### Client code + +gRPC generates two types for the client within a service namespace: + +1. `ClientProtocol`, and +2. `Client`. + +Like the service code, the full name includes the namespace. + +> Example: +> +> For the `BazService` in the `foo.bar.v1` package the client types would be: +> +> - `Foo_Bar_V1_BazService.ClientProtocol`, and +> - `Foo_Bar_V1_BazService.Client`. + +The `ClientProtocol` defines one requirement for each RPC in terms of +`ClientRequest` and `ClientResponse`. You don't need to implement the protocol +as `Client` provides a concrete implementation. + +gRPC also generates extensions on `ClientProtocol` to provide more ergonomic +APIs. These include versions which provide default arguments for various +parameters (like the message serializer and deserializers; call options and +response handler) and versions which don't use `ClientRequest` and +`ClientResponse` directly. diff --git a/Sources/GRPCProtobuf/Documentation.docc/Documentation.md b/Sources/GRPCProtobuf/Documentation.docc/Documentation.md index e5cb6ef..047ed75 100644 --- a/Sources/GRPCProtobuf/Documentation.docc/Documentation.md +++ b/Sources/GRPCProtobuf/Documentation.docc/Documentation.md @@ -21,6 +21,8 @@ This package provides three products: - - +- +- ### Serialization