RPC Protocol and Messages
The messages/payloads between Fed-BioMed components are defined and typed on the application and the communication (gRPC) layers. The application layer messages are typed and defined in order to use within the application, and the messages for communication are the protobuff object that is used for sending the data from one end-point to another. After a client or the server receives a protobuf it immediately converts it to corresponding dataclass defined in the application layer. Therefore, new messages introduced by developer should be defined in fedbiomed.common.message
module and should inherit from fedbiomed.common.message
. However, while some message types does not require to be modified or created as protocol buffers, some does. For example, application messages such as TrainRequest
, TrainReply
, SerachRequest
are typed generally using single protobuf as TaskResponse
, but some messages are defined in protocol files explicitly as it is in fedbiomed.message.module
(e.g Log
and Scalar
). Following sections will give the details of the messages used in communication and application layers.
RPC protocol buffers
Researcher component is the RPC server that provides RPC services for the nodes. The services and the corresponding message types for services are defined in fedbiomed/transport/protocols/researcher.proto
. The service and message instances are generated automatically after compiling the protocol files. It is mandatory to define a message for each service and use corresponding Python instance as input or output value of services implemented in the software.
Compiling proto files
Protocol files should be compiled to be able to create corresponding message and service objects in Python. Compilation can be done by executing {FEDBIOMED_DIR}/scripts/protoc.py
. The script will generate RPC service and protocol buffer for Python in the directory {FEDBIOMED_DIR}/fedbiomed/transport/protocols
.
Example protocol messages and corresponding data classes in the application layer
In researcher.proto
, the message TaskResponse
and TaskResult
is a general format representing the bytes of messages. These messages are converted to corresponding Message
dataclass of Fed-BioMed after they are received by node or researcher server (e.g fedbiomed.common.message.TaskResponse
). TaskResponse
or TaskResult
can wrap the message related to tasks as bytes. For example, The bytes_
field of TaskResult
can contain bytes of TrainReply
or SearchReply
. The reason that these messages are typed as bytes is that they can be big message that needs to be sent as stream. Please see the following train request example to understand the workflow in message serialization;
- Researcher creates
fedbiomed.common.message.TrainRequest
message to assign train task to the nodes. - The node executes
GetTask
service of researcher. - Researcher service takes the
TrainRequest
. 3.1 serializes as bytes. 3.2 createsfedbiomed.common.message.TaskResponse
from bytes 3.3 convertsTaskResponse
dataclass toTaskResponse
protobuf using methodfedbiomed.common.message.TaskResponse.to_proto()
- send
TaskResponse
to the node.
However, in researhcer.proto
some messages are typed and defined explicitly. For example, the message TrainRequest
is the input value for the service GetTaskUnary
that is executed by the nodes. TrainRequest
ptoobuf has also corresponding message type defined in fedbiomed.common.message
as TaskRequest
. Please see the implemented dataclass for TaskRequest
in message.py
module.
@dataclass
class TaskRequest(ProtoSerializableMessage, RequiresProtocolVersion):
"""Task request message from node to researcher"""
__PROTO_TYPE__ = r_pb2.TaskRequest
node: str
__PROTO_TYPE__
attribute to acknowledge which protobuf will be used for this message class to be able to send it through RPC call. Thanks to this declaration the message can be converted to proto using .to_proto()
or protobuf can be converted to python dataclass using .form_proto(proto)
methods.