Skip to content

Commit 8125093

Browse files
authored
Document how to create a public service with private implementation (#73)
Motivation: Sometimes libraries want to vend a public gRPC service but without exposing the generated types as part of the public API. This is easy to achieve but non-obvious. Modifications: - Add an article explaining how to achieve this Result: Easier for users to learn how to do this
1 parent 6bd6c50 commit 8125093

File tree

2 files changed

+46
-0
lines changed

2 files changed

+46
-0
lines changed
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# Public services with private implementations
2+
3+
Learn how to create a `public` gRPC service with private implementation details.
4+
5+
## Overview
6+
7+
It's not uncommon for a library to provide a gRPC service as part of its API.
8+
For example, the gRPC Swift Extras package provides implementations of the gRPC
9+
health and reflection services. Making the implementation of a service `public`
10+
would require its generated gRPC and message types to also be `public`. This is
11+
undesirable as it leaks implementation details into the public API of the
12+
package. This article explains how to keep the generated types private while
13+
making the service available as part of the public API.
14+
15+
## Hiding the implementation
16+
17+
You can hide the implementation details of your service by providing a wrapper
18+
type conforming to `RegistrableRPCService`. This is the protocol used by
19+
`GRPCServer` to register service methods with the server's router. Implementing
20+
`RegistrableRPCService` is straightforward and can delegate to the underlying
21+
service. This is demonstrated in the following code:
22+
23+
```swift
24+
public struct GreeterService: RegistrableRPCService {
25+
private var base: Greeter
26+
27+
public init() {
28+
self.base = Greeter()
29+
}
30+
31+
public func registerMethods<Transport>(
32+
with router: inout RPCRouter<Transport>
33+
) where Transport: ServerTransport {
34+
self.base.registerMethods(with: &router)
35+
}
36+
}
37+
```
38+
39+
In this example `Greeter` implements the underlying service and would conform to
40+
the generated service protocol but would have a non-public access level.
41+
`GreeterService` is a public wrapper type conforming to `RegistrableRPCService`
42+
which implements its only requirement, `registerMethods(with:)`, by calling
43+
through to the underlying implementation. The result is a service which can be
44+
registered with a server where none of the generated types are part of the
45+
public API.

Sources/GRPCProtobuf/Documentation.docc/Documentation.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ This package provides three products:
2323
- <doc:Generating-stubs>
2424
- <doc:API-stability-of-generated-code>
2525
- <doc:Understanding-the-generated-code>
26+
- <doc:Public-services-with-private-implementations>
2627

2728
### Serialization
2829

0 commit comments

Comments
 (0)