The protocol layer¶
Interface definition¶
All protocols are implemented by deriving from RPCProtocol
and implementing all of its members.
Every protocol deals with multiple kinds of structures: data
arguments are
always byte strings, either messages or replies, that are sent via or received
from a transport.
Protocol-specific subclasses of RPCRequest
and
RPCResponse
represent well-formed requests and responses.
Protocol specific subclasses of RPCErrorResponse
represent
errors and error responses.
Finally, if an error occurs during parsing of a request, a
BadRequestError
instance must be thrown. These need to be
subclassed for each protocol as well, since they generate error replies.
API Reference¶
-
class
tinyrpc.protocols.
RPCProtocol
¶ Bases:
abc.ABC
Abstract base class for all protocol implementations.
-
supports_out_of_order
= False¶ If true, this protocol can receive responses out of order correctly.
Note that this usually depends on the generation of unique_ids, the generation of these may or may not be thread safe, depending on the protocol. Ideally, only one instance of RPCProtocol should be used per client.
Type: bool
-
raises_errors
= True¶ If True, this protocol instance will raise an RPCError exception.
On receipt of an RPCErrorResponse instance an RPCError exception is raised. When this flag is False the RPCErrorResponse object is returned to the caller which is then responsible for handling the error.
Type: bool
-
create_request
(method: str, args: List[Any] = None, kwargs: Dict[str, Any] = None, one_way: bool = False) → tinyrpc.protocols.RPCRequest¶ Creates a new
RPCRequest
object.Called by the client when constructing a request. It is up to the implementing protocol whether or not
args
,kwargs
, one of these, both at once or none of them are supported.Parameters: Returns: A new request instance
Return type:
-
parse_request
(data: bytes) → tinyrpc.protocols.RPCRequest¶ De-serializes and validates a request.
Called by the server to reconstruct the serialized
RPCRequest
.Parameters: data (bytes) – The data stream received by the transport layer containing the serialized request. Returns: A reconstructed request. Return type: RPCRequest
-
parse_reply
(data: bytes) → Union[tinyrpc.protocols.RPCResponse, tinyrpc.protocols.RPCBatchResponse]¶ De-serializes and validates a response.
Called by the client to reconstruct the serialized
RPCResponse
.Parameters: data (bytes) – The data stream received by the transport layer containing the serialized response. Returns: A reconstructed response. Return type: RPCResponse
-
raise_error
(error: tinyrpc.protocols.RPCErrorResponse) → tinyrpc.exc.RPCError¶ Raises the exception in the client.
Called by the client to convert the
RPCErrorResponse
into an Exception and raise or return it depending on theraises_errors
attribute.Parameters: error ( RPCResponse
) – The error response received from the server.Return type: RPCError
whenraises_errors
is False.Raises: RPCError
whenraises_errors
is True.
-
-
class
tinyrpc.protocols.
RPCRequest
¶ Bases:
object
Defines a generic RPC request.
-
unique_id
= None¶ Correlation ID used to match request and response.
Type: int or str or None Protocol specific, may or may not be set. This value should only be set by
create_request()
.When the protocol permits it this ID allows servers to respond to requests out of order and allows clients to relate a response to the corresponding request.
Only supported if the protocol has its
supports_out_of_order
set toTrue
.Generated by the client, the server copies it from request to corresponding response.
-
method
= None¶ The name of the RPC function to be called.
Type: str The
method
attribute uses the name of the function as it is known by the public. TheRPCDispatcher
allows the use of public aliases in the@public
decorators. These are the names used in themethod
attribute.
-
args
= None¶ The positional arguments of the method call.
Type: list The contents of this list are the positional parameters for the
method
called. It is eventually called asmethod(*args)
.
-
kwargs
= None¶ The keyword arguments of the method call.
Type: dict The contents of this dict are the keyword parameters for the
method
called. It is eventually called asmethod(**kwargs)
.
-
error_respond
(error: Union[Exception, str]) → Optional[tinyrpc.protocols.RPCErrorResponse, None]¶ Creates an error response.
Create a response indicating that the request was parsed correctly, but an error has occurred trying to fulfill it.
This is an abstract method that must be overridden in a derived class.
Parameters: error (Exception or str) – An exception or a string describing the error. Returns: A response or None
to indicate that no error should be sent out.Return type: RPCErrorResponse
-
respond
(result: Any) → Optional[tinyrpc.protocols.RPCResponse, None]¶ Create a response.
Call this to return the result of a successful method invocation.
This creates and returns an instance of a protocol-specific subclass of
RPCResponse
.This is an abstract method that must be overridden in a derived class.
Parameters: result (Any type that can be serialized by the protocol.) – Passed on to new response instance. Returns: A response or None
to indicate this request does not expect a response.Return type: RPCResponse
-
-
class
tinyrpc.protocols.
RPCResponse
¶ Bases:
abc.ABC
Defines a generic RPC response.
Base class for all responses.
-
result
¶ When present this attribute contains the result of the RPC call. Otherwise the
error
attribute must be defined.Type: Any type that can be serialized by the protocol.
-
-
class
tinyrpc.protocols.
RPCErrorResponse
¶ Bases:
tinyrpc.protocols.RPCResponse
,abc.ABC
RPC error response class.
Base class for all deriving responses.
-
class
tinyrpc.exc.
BadRequestError
¶ Bases:
tinyrpc.exc.RPCError
,abc.ABC
Base class for all errors that caused the processing of a request to abort before a request object could be instantiated.
Batch protocols¶
Some protocols may support batch requests. In this case, they need to derive
from RPCBatchProtocol
.
Batch protocols differ in that their
parse_request()
method may return an instance of
RPCBatchRequest
. They also possess an addional method in
create_batch_request()
.
Handling a batch request is slightly different, while it supports
error_respond()
, to make actual responses,
create_batch_response()
needs to be used.
No assumptions are made whether or not it is okay for batch requests to be handled in parallel. This is up to the server/dispatch implementation, which must be chosen appropriately.
API Reference¶
-
class
tinyrpc.protocols.
RPCBatchProtocol
¶ Bases:
tinyrpc.protocols.RPCProtocol
,abc.ABC
Abstract base class for all batch protocol implementations.
-
create_batch_request
(requests: List[RPCRequest] = None) → tinyrpc.protocols.RPCBatchRequest¶ Create a new
RPCBatchRequest
object.Called by the client when constructing a request.
Parameters: requests ( list
orRPCRequest
) – A list of requests.Returns: A new request instance. Return type: RPCBatchRequest
-
-
class
tinyrpc.protocols.
RPCBatchRequest
¶ Bases:
list
Multiple requests batched together.
Protocols that support multiple requests in a single message use this to group them together. Note that not all protocols may support batch requests.
Handling a batch requests is done in any order, responses must be gathered in a batch response and be in the same order as their respective requests.
Any item of a batch request is either an
RPCRequest
or anBadRequestError
, which indicates that there has been an error in parsing the request.-
create_batch_response
() → Optional[tinyrpc.protocols.RPCBatchResponse, None]¶ Creates a response suitable for responding to this request.
This is an abstract method that must be overridden in a derived class.
Returns: An RPCBatchResponse
or None if no response is expected.Return type: RPCBatchResponse
-
-
class
tinyrpc.protocols.
RPCBatchResponse
¶ Bases:
list
Multiple response from a batch request. See
RPCBatchRequest
on how to handle.Items in a batch response need to be
RPCResponse
instances or None, meaning no reply should generated for the request.-
serialize
() → bytes¶ Returns a serialization of the batch response.
Converts the response into a bytes object that can be passed to and by the transport layer.
This is an abstract method that must be overridden in a derived class.
Returns: A bytes object to be passed on to a transport. Return type: bytes
-
ID Generators¶
By default, the JSONRPCProtocol
and MSGPACKRPCProtocol
classes
generates ids as sequential integers starting at 1.
If alternative id generation is needed, you may supply your own
generator.
Example¶
The following example shows how to use alternative id generators in a protocol that supports them.
from tinyrpc.protocols.jsonrpc import JSONRPCProtocol
def collatz_generator():
"""A sample generator for demonstration purposes ONLY."""
n = 27
while True:
if n % 2 != 0:
n = 3*n + 1
else:
n = n / 2
yield n
rpc = JSONRPCProtocol(id_generator=collatz_generator())
Supported protocols¶
Any supported protocol is used by instantiating its class and calling the
interface of RPCProtocol
. Note that constructors
are not part of the interface, any protocol may have specific arguments for its
instances.
Protocols usually live in their own module because they may need to import
optional modules that needn’t be a dependency for all of tinyrpc
.