Re-sync with internal repository
[hiphop-php.git] / third-party / thrift / src / thrift / doc / spec / protocol / interface / index.md
blobfe38c80729928a618af98aef39fc7529b154de94
1 ---
2 state: draft
3 ---
5 # Interface Protocols
7 This document describes the layer immediately preceding the transport protocol (eg. [Rocket](rocket.md)). This layer specifies how the request/response data must be serialized and formatted before being wrapped in the underlying transport protocol layer's message format.
9 ## Request
11 The client **must** take the user provided arguments to the Interface method and serialize the request as described in Serialization Details below. The client **may** compress the serialized request as described in [Request Compression](#request-compression). The name of the Interface method being requested as well as the [data protocol](../data.md) that was used to serialize the request **must** be included in the metadata associated with the request. The client may detect an exception while attempting to perform the request before a valid response is received from the server, in which case, it **must** be raised as a [Client Detected Exception](#client-detected-exceptions).
13 The client **must** specify the method name in the request as follows:
14 - For methods inside an interaction, the method name is `‹InteractionName›.‹MethodName›` where `‹InteractionName›` and `‹MethodName›` are the names in the IDL of the interaction and method respectively.
15 - For all other methods (including factory methods for interactions), the method name matches the name in the IDL.
17 ### Serialization Details
19 The parameters to an Interface method **must** be treated as fields of a Thrift struct with an empty name (`""`). The Field IDs **must** be the same as those specified in the IDL. If the Interface method has no parameters then the struct **must** have no fields. To prepare for sending the request through one of the underlying transport protocols, this unnamed struct **must** be serialized with one of Thrift’s [data protocols](../data.md).
21 For example, this method:
23 ```
24 i32 foo(1: i32 a, 2: string b)
25 ```
27 might be called with these fields set in the metadata:
29 ```
30   protocol = ProtocolId.COMPACT;
31   name = "foo";
32   kind = RpcKind.SINGLE_REQUEST_SINGLE_RESPONSE;
33   compression = CompressionAlgorithm.ZSTD;
34 ```
36 in which case it will have as its serialized request the result of placing the arguments in a
38 ```
39 struct ‹Anonymous› {
40   1: i32 a;
41   2: string b;
43 ```
45 passing the `‹Anonymous›` to a serializer for the [Compact Protocol](../data.md#compact-protocol) and passing the resulting string to a compressor for [zstd](https://facebook.github.io/zstd/).
47 ## Response
49 A response may be one of the following types:
51 - Declared response - responses that actually represent the response type of an Interface declared in the IDL. For example, the return type of a request-response method or the payload type of a stream.
52 - Declared exception
53 - Undeclared exception
54 - Any exception
55 - Internal server error
57 The server **must** serialize the response depending on the response type as described below. If the response is a declared response, declared exception, or undeclared exception, the server **should** compress the serialized response as described in [Response Compression](#response-compression).
59 ### Declared Response and Declared Exception
61 The Thrift struct used to represent declared responses and [declared exceptions](../../definition/exception.md#exceptions) **must** be a union with an empty name (`""`). The first field in the union with Field ID of `0` **must** be for the declared response. If the declared response type is `void` then the field for the declared response **must** be skipped. The Thrift struct **must** also have a field for each declared exception for that Interface with Field IDs matching those specified in the IDL. The correct field **must** be filled in by the server and then serialized using one of Thrift’s data protocols.
63 For example, this method:
65 ```
66 i32 foo(1: i32 a, 2: string b) throws (1: MyException e1, 2: OtherException e2);
67 ```
69 would use the following union as its response struct:
71 ```
72 union <Anonymous> {
73   0: i32 response;
74   1: MyException e1;
75   2: OtherException e2;
77 ```
79 If the response is a declared response, the response metadata **must** indicate that it is a declared response.
81 If the response is a declared exception, the response metadata **must** indicate that it is a declared exception and it **should** contain a [`ErrorClassification`](https://github.com/facebook/fbthrift/blob/main/thrift/lib/thrift/RpcMetadata.thrift#ErrorClassification) struct.
83 ### Undeclared Exception
85 [Undeclared exceptions](../../definition/exception.md#exceptions) **must** be sent through the response metadata and the metadata **must** indicate that the response is an undeclared exception and **must** contain the exception name and the message.
87 ### Any Exception
89 The response may also be an Any exception. This is an exception that is serialized using one of Thrift's data protocols and stored in a [`SemiAnyStruct`](https://github.com/facebook/fbthrift/blob/main/thrift/lib/thrift/any_rep.thrift#SemiAnyStruct). This `SemiAnyStruct` then must be serialized using one of Thrift's data protocols. If the protocol used to serialize the exception and the protocol used to serialize the `SemiAnyStruct` do not match, the `protocol` field in the `SemiAnyStruct` **must** be the data protocol that was used to serialize the exception. The response metadata **must** indicate that the response is an Any exception.
91 ### Internal Server Error
93 In addition to responses from the server handler, the server can also decide to reject a request for a variety of reasons, for example, load-shedding, invalid request, etc. In this case the server **should** send an exception containing one of the pre-defined error codes [here](https://github.com/facebook/fbthrift/blob/main/thrift/lib/cpp2/async/ResponseChannel.cpp).
95 ## Interfaces
97 ### Request-Response
99 To initiate a request-response, the client **must** make a request for a request-response method defined in the IDL. The request **must** follow the format defined in [Request](#request). After sending the request, the client **should** wait for a response from the server or throw a [Client Detected Exception](#client-detected-exceptions).
101 The server **must** execute the server handler for the requested method or reject the request with an [internal server error](#internal-server-error). Once the server handler finishes executing or throws an exception, the response **must** be sent using the format defined in [Response](#response).
103 ### Stream
105 #### Stream Request
107 To initiate a stream, the client **must** make a request for a stream method defined in the IDL. The request **must** follow the format defined in [Request](#request). After sending the request, the client **should** wait for a response from the server or throw a [Client Detected Exception](#client-detected-exceptions).
109 #### Stream Initial Response
111 The server **must** execute the server handler for the stream method or reject the request with an [internal server error](#internal-server-error). If the server handler finishes executing successfully, the server **must** send an initial response to the client containing the initial response type specified in the IDL (assumed to be `void` if no initial response type is specified). This initial response **must** be formatted as specified in [Response](#response) and will establish the stream.
113 If the request was rejected with an [internal server error](#internal-server-error) or the server handler threw an exception (declared or undeclared) the stream **must not** be established and the error **must** be sent to the client using the format specified in [Response](#response). In this case, the server **must not** send any stream payloads to the client.
115 #### Stream Payloads
117 Once the initial response is sent and the server has credits, the server **should** start sending stream payloads to the client. The stream payloads **must** be an actual payload, a declared exception, or an undeclared exception and they follow the format of these response types as defined in [Response](#response).
119 If the server sends a declared exception or an undeclared exception to the client, it acts as the termination of the stream and the server **must not** send any more payloads to the client.
121 #### Stream Cancellation
123 The client **may** send a cancellation signal to the server at any point after the stream is established. If the server receives a cancellation, it **should** stop sending stream payloads to the client.
125 #### Stream Completion
127 If the stream was established, the server **must** send a completion signal to the client once it is done sending all stream payloads to the client. The completion signal acts as a termination of the stream and the server **must not** send any payloads to the client after it has sent the completion signal.
129 #### Stream Flow Control
131 Thrift streaming **must** be flow-controlled using a credit mechanism. The client **must** give the server an initial set of credits that the server can use to send stream payloads. Each stream payload **must** consume one credit on the server. The server **must not** send any payloads if it has no credits until it receives more from the client.
133 #### Stream Expire Time
135 The server **may** specify a stream expire time which is the time the server **should** wait after exhausting all of its credits to receive more credits from the client. If the server doesn’t receive any credits after the stream expire time has elapsed, the server **should** terminate the stream with an [internal server error](#internal-server-error).
137 #### Stream Chunk Timeout
139 The client **may** specify a chunk timeout which is the time the client **should** wait for receiving a new stream payload from the server. If the client doesn’t receive a payload from the server for longer than the chunk timeout, it **should** cancel the stream and raise a [`TTransportException`](https://github.com/facebook/fbthrift/blob/main/thrift/lib/cpp/transport/TTransportException.h) with the type `TIMEOUT`.
141 ### Sink
143 #### Sink Request
145 To initiate a sink, the client **must** make a request for a sink method defined in the IDL. The request **must** follow the format defined in [Request](#request). After sending the request, the client **should** wait for a response from the server or throw a [Client Detected Exception](#client-detected-exceptions).
147 #### Sink Initial Response
149 The server **must** execute the server handler for the sink method or reject the request with an [internal server error](#internal-server-error). If the server handler finishes executing successfully, the server **must** send an initial response to the client containing the initial response type specified in the IDL (assumed to be `void` if no initial response type is specified). This initial response **must** be formatted as specified in [Response](#response) and will establish the sink.
151 If the request was rejected with an [internal server error](#internal-server-error) or the server handler threw an exception (declared or undeclared) the sink **must not** be established and the error **must** be sent to the client using the format specified in #Response. In this case, the client **must not** send any sink payloads to the server and the server **must not** send a final response to the client.
153 #### Sink Payloads
155 Once the initial response is received and the client has received an initial set of credits from the server, the client **should** start sending sink payloads to the server. The sink payloads **must** be an actual payload, a declared exception, or an undeclared exception and they follow the serialization format of these response types as defined in [Response](#response).
157 If the client sends a declared exception or an undeclared exception to the server, it **must not** send any more payloads to the server. The server **may** still respond with a final response.
159 #### Sink Completion
161 If the sink was established, the client **must** send a completion signal to the server once it is done sending all sink payloads to the server. The client **must not** send any payloads to the server after it has sent the completion signal.
163 #### Sink Final Response
165 If the sink was established, the server **must** send a final response to the client. The final response acts as a termination of the sink. The final response **may** be any one of the response types mentioned in [Response](#response). The server **may** send this final response before it receives the completion signal from the client.
167 #### Sink Flow Control
169 Thrift sinks **must** be flow-controlled using a credit mechanism. The server **must** send the client an initial set of credits after it receives a sink request. Each sink payload **must** consume one credit on the client. The client **must not** send any payloads if it has no credits until it receives more from the server.
171 #### Sink Chunk Timeout
173 The server **may** specify a chunk timeout which is the time the server **should** wait for receiving a new sink payload from the client. If the server doesn’t receive a payload from the client for longer than the chunk timeout, it **should** terminate the sink by sending an [internal server error](#internal-server-error).
175 ### Interactions
177 Requests that are part of the interaction **must** be sent over the same connection to the server. Each interaction **must** have an ID that is unique to the connection. The server **must** maintain the state that is associated with each interaction so that subsequent requests can use that state.
179 All requests in an interaction, including the factory function if used, **must** reach the server in the order they are sent by the client. The server **may** begin processing subsequent requests before the earlier ones complete, provided they are started in order.
181 The RPC contracts of member requests are otherwise handled the same as if the requests were not in an interaction. A single interaction **may** include multiple streams/sinks, and these are flow-controlled independently.
183 #### Creation
185 Interactions can be created in two different ways as described below.
187 ##### Factory Functions
189 Factory functions are an eager way to create an interaction, in that the interaction is created when the factory function is called. The factory function request **must** have metadata indicating that it is creating an interaction. The server **must** execute the server handler for the factory function or reject the request with an [internal server error](#internal-server-error). If the server handler finishes executing successfully, the server **must** send a response to the client containing the response type specified in the IDL (assumed to be `void` if no response type is specified). Subsequent requests in the interaction **must** contain the interaction ID in their metadata.
191 ##### Constructors (Deprecated)
193 Interaction constructors are a lazy way to create an interaction, in that the interaction is not created until the first request that is part of the interaction is sent. This first request **must** have metadata indicating that it is the first request. Subsequent requests **must** contain the interaction ID in their metadata.
195 #### Termination
197 Only the client can terminate the interaction and it can do so at any time after the interaction has been created, including with requests outstanding. When an interaction is terminated, the client **must** send a termination signal to the server. The server **must** finish processing any outstanding requests when the termination signal is received, including waiting for streams/sinks to complete normally; terminating an interaction **must not** cancel member streams/sinks. The server **must** invoke the following two hooks:
198 - onTermination: scheduled immediately when termination signal is received, without waiting for outstanding requests to complete.
199 - destructor: scheduled once all responses have been sent back to the client and streams/sinks completed.
201 #### Serial interactions
203 For interactions annotated `(serial)` the server **must** ensure no more than one request is being executed at a time by buffering concurrent requests and executing them sequentially. The client **may** send multiple requests in such an interaction without waiting for responses in between.
205 ### Oneway Requests (Deprecated)
207 To perform a oneway request, the client **must** make a request for a oneway request method defined in the IDL. The request **must** follow the format defined in [Request](#request). The client **must not** wait for a response from the server. The client **should** raise a [Client Detected Exception](#client-detected-exceptions) if there is an exception while the client is attempting to send the request. The server **must** execute the server handler for the requested method or drop the request.
209 ## Timeouts
211 ### Client Timeout
213 The client **may** specify a timeout value for a request which is the amount of time it is willing to wait for a response from the server before giving up and raising a [`TTransportException`](https://github.com/facebook/fbthrift/blob/main/thrift/lib/cpp/transport/TTransportException.h) with the type `TIMEOUT`. This timeout value **should** also be sent to the server in the request metadata. If set, the server **should** only start processing the request from the request queue if the client timeout has not already expired. If it has already expired, the server **should** instead drop the request and send an [internal server error](#internal-server-error) with the code [`kTaskExpiredErrorCode`](https://github.com/facebook/fbthrift/blob/main/thrift/lib/cpp2/async/ResponseChannel.cpp).
215 ### Queue Timeout
217 The client **may** specify a queue timeout value in the request metadata. The queue timeout is the amount of time the server **should** allow the request to sit in its request queue before giving up and dropping the request. If the request sits in the request queue for longer than the queue timeout value, the server **should not** start processing the request and instead send an [internal server error](#internal-server-error) with the code [`kServerQueueTimeoutErrorCode`](https://github.com/facebook/fbthrift/blob/main/thrift/lib/cpp2/async/ResponseChannel.cpp).
219 ## Compression
221 Request and response compression is supported in Thrift using one of the following algorithms:
223 - ZLIB
224 - ZSTD
226 ### Request Compression
228 Requests **may** be compressed by the client after they have been serialized as described in #Request-serialization. If the request was compressed, the compression algorithm **must** be specified in the request metadata.
230 ### Response Compression
232 The client **may** request the server to compress responses based on the size of the response. If requesting compression, the client **should** specify the compression algorithm and the minimum response size that **should** trigger compression in the request metadata. If requested by the client, the server **should** compress the response after it has been serialized using the compression algorithm specified by the client. If not requested by the client, the server **may** compress the response and it **may** use any supported compression algorithm. If the response was compressed, the compression algorithm **must** be specified in the response metadata.
234 ## Client Detected Exceptions
236 Exceptions that are detected purely by the client (rather than being sent over the wire from the server) are represented as [`TTransportException`](https://github.com/facebook/fbthrift/blob/main/thrift/lib/cpp/transport/TTransportException.h). Some of the reasons why a client detected exception may be raised include:
238 - Timeout (server non-responsive)
239 - Corrupted data (checksum mismatch)
240 - Socket errors
241 - [Many more](https://github.com/facebook/fbthrift/blob/main/thrift/lib/cpp/transport/TTransportException.h#TTransportExceptionType)
243 ## Underlying Transport Protocols
245 The Thrift Interface protocol is a higher level abstraction that defines the behavior of various interfaces, however, it must utilize a lower level transport protocol to actually send requests and receive responses.
247 ### Rocket Protocol
249 [Rocket protocol](rocket.md) is an implementation of the Thrift Interface protocol using the [RSocket protocol](https://rsocket.io/).
251 ### Header Protocol (Deprecated)
253 Header protocol is a deprecated transport protocol.