Skip to content
callers.py 2.46 KiB
Newer Older
Antoine Millet's avatar
Antoine Millet committed
import threading

from sjrpc.core.exceptions import RpcError

ERRMSG_RPCERR = ('Unable to send reply to the peer: %s (this error is usualy '
                 'raised when connection is lost while handler function '
                 'execution)')


Antoine Millet's avatar
Antoine Millet committed
class RpcCaller(object):
    '''
    A caller execute a callable (function, method, class which implement the
    :meth:`__call__` method...) in a particular context (threaded or
    "timeouted" for example), and return the result (or the exception) to the
Antoine Millet's avatar
Antoine Millet committed
    peer through it :class:`RpcConnection` object.
    '''

    def __init__(self, request, protocol, func):
Antoine Millet's avatar
Antoine Millet committed
        self._request = request
Antoine Millet's avatar
Antoine Millet committed
        self._func = func

        # Apply the request decorator
        #request_decorator = connection.request_decorator
        #if request_decorator is not None:
        #    self._func = request_decorator(self._func)

Antoine Millet's avatar
Antoine Millet committed
    def run(self):
        '''
        Run the callable and return the result (or the exception) to the peer.
        '''
        msg_id = self._request['id']
        args = self._request['args']
        kwargs = self._request['kwargs']

        if getattr(self._func, '__pass_rpc__', False):
            args.insert(0, self._protocol)
        if getattr(self._func, '__pass_connection__', False):
            args.insert(0, self._protocol.connection)
Antoine Millet's avatar
Antoine Millet committed
        try:
            returned = self._func(*args, **kwargs)
        except Exception as err:
            try:
                self._protocol.error(msg_id, message=str(err),
                                       error=err.__class__.__name__)
            except RpcError as err:
                self._protocol.connection.logger.error(ERRMSG_RPCERR, err)
Antoine Millet's avatar
Antoine Millet committed
        else:
            try:
                self._protocol.response(msg_id, returned=returned)
            except RpcError as err:
                self._protocol.connection.logger.error(ERRMSG_RPCERR, err)

Antoine Millet's avatar
Antoine Millet committed
    def start(self):
        '''
        Start execution of the callable, the most of time, it just call
Antoine Millet's avatar
Antoine Millet committed
        :meth:`run` method.
        '''
        self.run()


class ThreadedRpcCaller(RpcCaller):
Antoine Millet's avatar
Antoine Millet committed
    '''
    A caller which make the call into a separated thread.
    '''
Antoine Millet's avatar
Antoine Millet committed
    def __init__(self, *args, **kwargs):
        super(ThreadedRpcCaller, self).__init__(*args, **kwargs)
        self._thread = threading.Thread(target=self.run)
        self._thread.name = 'Processing of call: %s' % self._request['id']
Antoine Millet's avatar
Antoine Millet committed
        self._thread.daemon = True
Antoine Millet's avatar
Antoine Millet committed
    def start(self):
        self._thread.start()