xref: /aosp_15_r20/external/pigweed/pw_rpc/design.rst (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1*61c4878aSAndroid Build Coastguard Worker.. _module-pw_rpc-design:
2*61c4878aSAndroid Build Coastguard Worker
3*61c4878aSAndroid Build Coastguard Worker================
4*61c4878aSAndroid Build Coastguard WorkerDesign & roadmap
5*61c4878aSAndroid Build Coastguard Worker================
6*61c4878aSAndroid Build Coastguard Worker.. pigweed-module-subpage::
7*61c4878aSAndroid Build Coastguard Worker   :name: pw_rpc
8*61c4878aSAndroid Build Coastguard Worker
9*61c4878aSAndroid Build Coastguard Worker.. _module-pw_rpc-design-overview:
10*61c4878aSAndroid Build Coastguard Worker
11*61c4878aSAndroid Build Coastguard Worker--------
12*61c4878aSAndroid Build Coastguard WorkerOverview
13*61c4878aSAndroid Build Coastguard Worker--------
14*61c4878aSAndroid Build Coastguard WorkerThe semantics of ``pw_rpc`` are similar to `gRPC
15*61c4878aSAndroid Build Coastguard Worker<https://grpc.io/docs/what-is-grpc/core-concepts/>`_.
16*61c4878aSAndroid Build Coastguard Worker
17*61c4878aSAndroid Build Coastguard Worker.. _module-pw_rpc-design-lifecycle:
18*61c4878aSAndroid Build Coastguard Worker
19*61c4878aSAndroid Build Coastguard WorkerRPC call lifecycle
20*61c4878aSAndroid Build Coastguard Worker==================
21*61c4878aSAndroid Build Coastguard WorkerIn ``pw_rpc``, an RPC begins when the client sends an initial packet. The server
22*61c4878aSAndroid Build Coastguard Workerreceives the packet, looks up the relevant service method, then calls into the
23*61c4878aSAndroid Build Coastguard WorkerRPC function. The RPC is considered active until the server sends a status to
24*61c4878aSAndroid Build Coastguard Workerfinish the RPC. The client may terminate an ongoing RPC by cancelling it.
25*61c4878aSAndroid Build Coastguard WorkerMultiple concurrent RPC requests to the same method may be made simultaneously
26*61c4878aSAndroid Build Coastguard Worker(Note: Concurrent requests are not yet possible using the Java client. See
27*61c4878aSAndroid Build Coastguard Worker`Issue 237418397 <https://issues.pigweed.dev/issues/237418397>`_).
28*61c4878aSAndroid Build Coastguard Worker
29*61c4878aSAndroid Build Coastguard WorkerDepending the type of RPC, the client and server exchange zero or more protobuf
30*61c4878aSAndroid Build Coastguard Workerrequest or response payloads. There are four RPC types:
31*61c4878aSAndroid Build Coastguard Worker
32*61c4878aSAndroid Build Coastguard Worker* **Unary**. The client sends one request and the server sends one
33*61c4878aSAndroid Build Coastguard Worker  response with a status.
34*61c4878aSAndroid Build Coastguard Worker* **Server streaming**. The client sends one request and the server sends zero
35*61c4878aSAndroid Build Coastguard Worker  or more responses followed by a status.
36*61c4878aSAndroid Build Coastguard Worker* **Client streaming**. The client sends zero or more requests and the server
37*61c4878aSAndroid Build Coastguard Worker  sends one response with a status.
38*61c4878aSAndroid Build Coastguard Worker* **Bidirectional streaming**. The client sends zero or more requests and the
39*61c4878aSAndroid Build Coastguard Worker  server sends zero or more responses followed by a status.
40*61c4878aSAndroid Build Coastguard Worker
41*61c4878aSAndroid Build Coastguard Worker.. _module-pw_rpc-design-events:
42*61c4878aSAndroid Build Coastguard Worker
43*61c4878aSAndroid Build Coastguard WorkerEvents
44*61c4878aSAndroid Build Coastguard Worker------
45*61c4878aSAndroid Build Coastguard WorkerThe key events in the RPC lifecycle are:
46*61c4878aSAndroid Build Coastguard Worker
47*61c4878aSAndroid Build Coastguard Worker* **Start**. The client initiates the RPC. The server's RPC body executes.
48*61c4878aSAndroid Build Coastguard Worker* **Finish**. The server sends a status and completes the RPC. The client calls
49*61c4878aSAndroid Build Coastguard Worker  a callback.
50*61c4878aSAndroid Build Coastguard Worker* **Request**. The client sends a request protobuf. The server calls a callback
51*61c4878aSAndroid Build Coastguard Worker  when it receives it. In unary and server streaming RPCs, there is only one
52*61c4878aSAndroid Build Coastguard Worker  request and it is handled when the RPC starts.
53*61c4878aSAndroid Build Coastguard Worker* **Response**. The server sends a response protobuf. The client calls a
54*61c4878aSAndroid Build Coastguard Worker  callback when it receives it. In unary and client streaming RPCs, there is
55*61c4878aSAndroid Build Coastguard Worker  only one response and it is handled when the RPC completes.
56*61c4878aSAndroid Build Coastguard Worker* **Error**. The server or client terminates the RPC abnormally with a status.
57*61c4878aSAndroid Build Coastguard Worker  The receiving endpoint calls a callback.
58*61c4878aSAndroid Build Coastguard Worker* **Request Completion**. The client sends a message that it would like to
59*61c4878aSAndroid Build Coastguard Worker  request call completion. The server calls a callback when it receives it. Some
60*61c4878aSAndroid Build Coastguard Worker  servers may ignore the request completion message. In client and bidirectional
61*61c4878aSAndroid Build Coastguard Worker  streaming RPCs, this also indicates that client has finished sending requests.
62*61c4878aSAndroid Build Coastguard Worker
63*61c4878aSAndroid Build Coastguard Worker.. _module-pw_rpc-design-services:
64*61c4878aSAndroid Build Coastguard Worker
65*61c4878aSAndroid Build Coastguard WorkerServices
66*61c4878aSAndroid Build Coastguard Worker========
67*61c4878aSAndroid Build Coastguard WorkerA service is a logical grouping of RPCs defined within a ``.proto`` file. ``pw_rpc``
68*61c4878aSAndroid Build Coastguard Workeruses these ``.proto`` definitions to generate code for a base service, from which
69*61c4878aSAndroid Build Coastguard Workeruser-defined RPCs are implemented.
70*61c4878aSAndroid Build Coastguard Worker
71*61c4878aSAndroid Build Coastguard Worker``pw_rpc`` supports multiple protobuf libraries, and the generated code API
72*61c4878aSAndroid Build Coastguard Workerdepends on which is used.
73*61c4878aSAndroid Build Coastguard Worker
74*61c4878aSAndroid Build Coastguard WorkerServices must be registered with a server in order to call their methods.
75*61c4878aSAndroid Build Coastguard WorkerServices may later be unregistered, which cancels calls for methods in that
76*61c4878aSAndroid Build Coastguard Workerservice and prevents future calls to them, until the service is re-registered.
77*61c4878aSAndroid Build Coastguard Worker
78*61c4878aSAndroid Build Coastguard WorkerBackground:
79*61c4878aSAndroid Build Coastguard Worker
80*61c4878aSAndroid Build Coastguard Worker* `Protocol Buffer service
81*61c4878aSAndroid Build Coastguard Worker  <https://developers.google.com/protocol-buffers/docs/proto3#services>`_
82*61c4878aSAndroid Build Coastguard Worker* `gRPC service definition
83*61c4878aSAndroid Build Coastguard Worker  <https://grpc.io/docs/what-is-grpc/core-concepts/#service-definition>`_
84*61c4878aSAndroid Build Coastguard Worker
85*61c4878aSAndroid Build Coastguard Worker.. _module-pw_rpc-design-status-codes:
86*61c4878aSAndroid Build Coastguard Worker
87*61c4878aSAndroid Build Coastguard WorkerStatus codes
88*61c4878aSAndroid Build Coastguard Worker============
89*61c4878aSAndroid Build Coastguard Worker``pw_rpc`` call objects (``ClientReaderWriter``, ``ServerReaderWriter``, etc.)
90*61c4878aSAndroid Build Coastguard Workeruse certain status codes to indicate what occurred. These codes are returned
91*61c4878aSAndroid Build Coastguard Workerfrom functions like ``Write()`` or ``Finish()``.
92*61c4878aSAndroid Build Coastguard Worker
93*61c4878aSAndroid Build Coastguard Worker* ``OK`` -- The operation succeeded.
94*61c4878aSAndroid Build Coastguard Worker* ``UNAVAILABLE`` -- The channel is not currently registered with the server or
95*61c4878aSAndroid Build Coastguard Worker  client.
96*61c4878aSAndroid Build Coastguard Worker* ``UNKNOWN`` -- Sending a packet failed due to an unrecoverable
97*61c4878aSAndroid Build Coastguard Worker  :cpp:func:`pw::rpc::ChannelOutput::Send` error.
98*61c4878aSAndroid Build Coastguard Worker
99*61c4878aSAndroid Build Coastguard Worker.. _module-pw_rpc-design-unrequested-responses:
100*61c4878aSAndroid Build Coastguard Worker
101*61c4878aSAndroid Build Coastguard WorkerUnrequested responses
102*61c4878aSAndroid Build Coastguard Worker=====================
103*61c4878aSAndroid Build Coastguard Worker``pw_rpc`` supports sending responses to RPCs that have not yet been invoked by
104*61c4878aSAndroid Build Coastguard Workera client. This is useful in testing and in situations like an RPC that triggers
105*61c4878aSAndroid Build Coastguard Workerreboot. After the reboot, the device opens the writer object and sends its
106*61c4878aSAndroid Build Coastguard Workerresponse to the client.
107*61c4878aSAndroid Build Coastguard Worker
108*61c4878aSAndroid Build Coastguard WorkerThe C++ API for opening a server reader/writer takes the generated RPC function
109*61c4878aSAndroid Build Coastguard Workeras a template parameter. The server to use, channel ID, and service instance are
110*61c4878aSAndroid Build Coastguard Workerpassed as arguments. The API is the same for all RPC types, except the
111*61c4878aSAndroid Build Coastguard Workerappropriate reader/writer class must be used.
112*61c4878aSAndroid Build Coastguard Worker
113*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++
114*61c4878aSAndroid Build Coastguard Worker
115*61c4878aSAndroid Build Coastguard Worker   // Open a ServerWriter for a server streaming RPC.
116*61c4878aSAndroid Build Coastguard Worker   auto writer = RawServerWriter::Open<pw_rpc::raw::ServiceName::MethodName>(
117*61c4878aSAndroid Build Coastguard Worker       server, channel_id, service_instance);
118*61c4878aSAndroid Build Coastguard Worker
119*61c4878aSAndroid Build Coastguard Worker   // Send some responses, even though the client has not yet called this RPC.
120*61c4878aSAndroid Build Coastguard Worker   CHECK_OK(writer.Write(encoded_response_1));
121*61c4878aSAndroid Build Coastguard Worker   CHECK_OK(writer.Write(encoded_response_2));
122*61c4878aSAndroid Build Coastguard Worker
123*61c4878aSAndroid Build Coastguard Worker   // Finish the RPC.
124*61c4878aSAndroid Build Coastguard Worker   CHECK_OK(writer.Finish(OkStatus()));
125*61c4878aSAndroid Build Coastguard Worker
126*61c4878aSAndroid Build Coastguard Worker.. _module-pw_rpc-design-errata:
127*61c4878aSAndroid Build Coastguard Worker
128*61c4878aSAndroid Build Coastguard WorkerErrata
129*61c4878aSAndroid Build Coastguard Worker------
130*61c4878aSAndroid Build Coastguard WorkerPrior to support for concurrent requests to a single method, no identifier was
131*61c4878aSAndroid Build Coastguard Workerpresent to distinguish different calls to the same method. When a "call ID"
132*61c4878aSAndroid Build Coastguard Workerfeature was first introduced to solve this issue, existing clients and servers
133*61c4878aSAndroid Build Coastguard Worker(1) set this value to zero and (2) ignored this value.
134*61c4878aSAndroid Build Coastguard Worker
135*61c4878aSAndroid Build Coastguard WorkerWhen initial support for concurrent methods was added, a separate "open call ID"
136*61c4878aSAndroid Build Coastguard Workerwas introduced to distinguish unrequested responses. However, legacy servers
137*61c4878aSAndroid Build Coastguard Workerbuilt prior to this change continue to send unrequested responses with call ID
138*61c4878aSAndroid Build Coastguard Workerzero. Prior to `this fix
139*61c4878aSAndroid Build Coastguard Worker<https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/192311>`_, clients
140*61c4878aSAndroid Build Coastguard Workerwhich used "open call ID" would not accept unrequested responses from legacy
141*61c4878aSAndroid Build Coastguard Workerservers. Clients built after that change will accept unrequested responses which
142*61c4878aSAndroid Build Coastguard Workeruse both "open call ID" and call ID zero.
143*61c4878aSAndroid Build Coastguard Worker
144*61c4878aSAndroid Build Coastguard WorkerSee `Issue 237418397 <https://issues.pigweed.dev/issues/237418397>`_ for more
145*61c4878aSAndroid Build Coastguard Workerdetails and discussion.
146*61c4878aSAndroid Build Coastguard Worker
147*61c4878aSAndroid Build Coastguard Worker.. _module-pw_rpc-design-naming:
148*61c4878aSAndroid Build Coastguard Worker
149*61c4878aSAndroid Build Coastguard Worker------
150*61c4878aSAndroid Build Coastguard WorkerNaming
151*61c4878aSAndroid Build Coastguard Worker------
152*61c4878aSAndroid Build Coastguard Worker
153*61c4878aSAndroid Build Coastguard WorkerFor upstream Pigweed services, this naming style is a requirement. Note that
154*61c4878aSAndroid Build Coastguard Workersome services created before this was established may use non-compliant
155*61c4878aSAndroid Build Coastguard Workernames. For Pigweed users, this naming style is a suggestion.
156*61c4878aSAndroid Build Coastguard Worker
157*61c4878aSAndroid Build Coastguard WorkerReserved names
158*61c4878aSAndroid Build Coastguard Worker==============
159*61c4878aSAndroid Build Coastguard Worker``pw_rpc`` reserves a few service method names so they can be used for generated
160*61c4878aSAndroid Build Coastguard Workerclasses. The following names cannot be used for service methods:
161*61c4878aSAndroid Build Coastguard Worker
162*61c4878aSAndroid Build Coastguard Worker- ``Client``
163*61c4878aSAndroid Build Coastguard Worker- ``Service``
164*61c4878aSAndroid Build Coastguard Worker- Any reserved words in the languages ``pw_rpc`` supports (e.g. ``class``).
165*61c4878aSAndroid Build Coastguard Worker
166*61c4878aSAndroid Build Coastguard Worker``pw_rpc`` does not reserve any service names, but the restriction of avoiding
167*61c4878aSAndroid Build Coastguard Workerreserved words in supported languages applies.
168*61c4878aSAndroid Build Coastguard Worker
169*61c4878aSAndroid Build Coastguard WorkerService naming style
170*61c4878aSAndroid Build Coastguard Worker====================
171*61c4878aSAndroid Build Coastguard Worker``pw_rpc`` service names should use capitalized camel case and should not use
172*61c4878aSAndroid Build Coastguard Workerthe term "Service". Appending "Service" to a service name is redundant, similar
173*61c4878aSAndroid Build Coastguard Workerto appending "Class" or "Function" to a class or function name. The
174*61c4878aSAndroid Build Coastguard WorkerC++ implementation class may use "Service" in its name, however.
175*61c4878aSAndroid Build Coastguard Worker
176*61c4878aSAndroid Build Coastguard WorkerFor example, a service for accessing a file system should simply be named
177*61c4878aSAndroid Build Coastguard Worker``service FileSystem``, rather than ``service FileSystemService``, in the
178*61c4878aSAndroid Build Coastguard Worker``.proto`` file.
179*61c4878aSAndroid Build Coastguard Worker
180*61c4878aSAndroid Build Coastguard Worker.. code-block:: protobuf
181*61c4878aSAndroid Build Coastguard Worker
182*61c4878aSAndroid Build Coastguard Worker   // file.proto
183*61c4878aSAndroid Build Coastguard Worker   package pw.file;
184*61c4878aSAndroid Build Coastguard Worker
185*61c4878aSAndroid Build Coastguard Worker   service FileSystem {
186*61c4878aSAndroid Build Coastguard Worker       rpc List(ListRequest) returns (stream ListResponse);
187*61c4878aSAndroid Build Coastguard Worker   }
188*61c4878aSAndroid Build Coastguard Worker
189*61c4878aSAndroid Build Coastguard WorkerThe C++ service implementation class may append "Service" to the name.
190*61c4878aSAndroid Build Coastguard Worker
191*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp
192*61c4878aSAndroid Build Coastguard Worker
193*61c4878aSAndroid Build Coastguard Worker   // file_system_service.h
194*61c4878aSAndroid Build Coastguard Worker   #include "pw_file/file.raw_rpc.pb.h"
195*61c4878aSAndroid Build Coastguard Worker
196*61c4878aSAndroid Build Coastguard Worker   namespace pw::file {
197*61c4878aSAndroid Build Coastguard Worker
198*61c4878aSAndroid Build Coastguard Worker   class FileSystemService : public pw_rpc::raw::FileSystem::Service<FileSystemService> {
199*61c4878aSAndroid Build Coastguard Worker     void List(ConstByteSpan request, RawServerWriter& writer);
200*61c4878aSAndroid Build Coastguard Worker   };
201*61c4878aSAndroid Build Coastguard Worker
202*61c4878aSAndroid Build Coastguard Worker   }  // namespace pw::file
203*61c4878aSAndroid Build Coastguard Worker
204*61c4878aSAndroid Build Coastguard Worker.. _module-pw_rpc-roadmap:
205*61c4878aSAndroid Build Coastguard Worker
206*61c4878aSAndroid Build Coastguard Worker-------
207*61c4878aSAndroid Build Coastguard WorkerRoadmap
208*61c4878aSAndroid Build Coastguard Worker-------
209*61c4878aSAndroid Build Coastguard WorkerConcurrent requests were not initially supported in pw_rpc (added in `C++
210*61c4878aSAndroid Build Coastguard Worker<https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/109077>`_, `Python
211*61c4878aSAndroid Build Coastguard Worker<https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/139610>`_, and
212*61c4878aSAndroid Build Coastguard Worker`TypeScript
213*61c4878aSAndroid Build Coastguard Worker<https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/160792>`_). As a
214*61c4878aSAndroid Build Coastguard Workerresult, some user-written service implementations may not expect or correctly
215*61c4878aSAndroid Build Coastguard Workersupport concurrent requests.
216