Controller

Controller class

To declare controller class you should inherit it from tavrida.service.ServiceController and decorate with tavrida.dispatcher.rpc_service() decorator

1
2
3
4
5
6
from tavrida import dispatcher
from tavrida import service

@dispatcher.rpc_service("test_hello")
class HelloController(service.ServiceController):
    pass

Request handler can return 2 type of responses (dict, tavrida.messages.Response, tavrida.messages.Error) or None value.

If dict is returned it will be converted to the tavrida.messages.Response object. If any exception raises during message processing it is converted to tavrida.messages.Error object.

But you can, of course, return tavrida.messages.Response or tavrida.messages.Error object explicitly.

Controller is instantiated on tavrida.server.Server start. Each service controller class owns a tavrida.dispatcher.Dispatcher and discovery object.

If you are planning to execute calls from any of the handlers you should bind discovery object to the service class before tavrida.server.Server starts.

1
2
disc.register_remote_service("remote_service", "remote_service_exchange")
HelloController.set_discovery(disc)

Handlers

Handlers are methods of service controllers that are called on message ( tavrida.messages.IncomingRequest request, tavrida.messages.IncomingResponse response, tavrida.messages.IncomingError error, tavrida.messages.IncomingNotification notification) arrival.

Each handler is bound to tavrida.entry_point.EntryPoint which can be considered as an address to deliver the message.

Each handler receives two parameters (at first two positions): message and tavrida.proxies.RPCProxy. Class of incoming message depends on handler type. Using tavrida.proxies.RPCProxy object you can execute calls to remote services. In such calls the service’s discovery object is used.

All following parameters are custom parameters of a particular method. In the following example param is such parameter.

Request handler

tavrida.messages.IncomingRequest routing is based on the name of local service entry point. For example for test_hello service the correct entry point service value is test_hello

1
2
3
@dispatcher.rpc_method(service="test_hello", method="hello")
def handler(self, request, proxy, param):
    return {"parameter": "value"}

Response handler

tavrida.messages.IncomingResponse routing is based on the name of remote service entry point. For example for test_hello service and remote entry point remote_service.remote_method the correct entry point value is remote_service.remote_method

1
2
3
@dispatcher.rpc_response_method(service="remote_service", method="remote_method")
def world_resp(self, response, proxy, param):
    pass

Error handler

tavrida.messages.IncomingError routing is based on the name of remote service entry point. For example for test_hello service and remote entry point remote_service.remote_method the correct entry point value is remote_service.remote_method Error handler takes strictly two parameters. The first (error) parameter has a property payload that is a dict of 3 keys: class, message, name. All these keys are mapped to string values.

1
2
3
@dispatcher.rpc_error_method(service="remote_service", method="remote_method")
def world_error(self, error, proxy):
    pass

Subscription handler

tavrida.messages.IncomingNotification routing is based on the name of remote publisher entry point. Such entry point can be considered as notification topic. For example for test_hello service and remote entry point remote_service.remote_method the correct entry point value is remote_service.remote_method

1
2
3
@dispatcher.subscription_method(service="remote_service", method="remote_method")
def hello_subscription(self, notification, proxy, param):
    pass

Resulting code example

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
from tavrida import dispatcher
from tavrida import service

@dispatcher.rpc_service("test_hello")
class HelloController(service.ServiceController):

    @dispatcher.rpc_method(service="test_hello", method="hello")
    def handler(self, request, proxy, param):
        return {"parameter": "value"}

    @dispatcher.rpc_response_method(service="remote_service", method="remote_method")
    def world_resp(self, response, proxy, param):
        pass

    @dispatcher.rpc_error_method(service="remote_service", method="remote_method")
    def world_error(self, error, proxy):
        pass

    @dispatcher.subscription_method(service="remote_service", method="remote_method")
    def hello_subscription(self, notification, proxy, param):
        pass