A class for invoking methods on remote servers.
The RPCClient class is responsible for sending method invocations to remote servers via a messaging transport.
A default target is supplied to the RPCClient constructor, but target attributes can be overridden for individual method invocations using the prepare() method.
A method invocation consists of a request context dictionary, a method name and a dictionary of arguments. A cast() invocation just sends the request and returns immediately. A call() invocation waits for the server to send a return value.
This class is intended to be used by wrapping it in another class which provides methods on the subclass to perform the remote invocation using call() or cast():
class TestClient(object):
def __init__(self, transport):
target = messaging.Target(topic='test', version='2.0')
self._client = messaging.RPCClient(transport, target)
def test(self, ctxt, arg):
return self._client.call(ctxt, 'test', arg=arg)
An example of using the prepare() method to override some attributes of the default target:
def test(self, ctxt, arg):
cctxt = self._client.prepare(version='2.5')
return cctxt.call(ctxt, 'test', arg=arg)
RPCClient have a number of other properties - for example, timeout and version_cap - which may make sense to override for some method invocations, so they too can be passed to prepare():
def test(self, ctxt, arg):
cctxt = self._client.prepare(timeout=10)
return cctxt.call(ctxt, 'test', arg=arg)
However, this class can be used directly without wrapping it another class. For example:
transport = messaging.get_transport(cfg.CONF)
target = messaging.Target(topic='test', version='2.0')
client = messaging.RPCClient(transport, target)
client.call(ctxt, 'test', arg=arg)
but this is probably only useful in limited circumstances as a wrapper class will usually help to make the code much more obvious.
By default, cast() and call() will block until the message is successfully sent. However, the retry parameter can be used to have message sending fail with a MessageDeliveryFailure after the given number of retries. For example:
client = messaging.RPCClient(transport, target, retry=None)
client.call(ctxt, 'sync')
try:
client.prepare(retry=0).cast(ctxt, 'ping')
except messaging.MessageDeliveryFailure:
LOG.error("Failed to send ping message")
Invoke a method and wait for a reply.
Method arguments must either be primitive types or types supported by the client’s serializer (if any). Similarly, the request context must be a dict unless the client’s serializer supports serializing another type.
The semantics of how any errors raised by the remote RPC endpoint method are handled are quite subtle.
Firstly, if the remote exception is contained in one of the modules listed in the allow_remote_exmods messaging.get_transport() parameter, then it this exception will be re-raised by call(). However, such locally re-raised remote exceptions are distinguishable from the same exception type raised locally because re-raised remote exceptions are modified such that their class name ends with the ‘_Remote’ suffix so you may do:
if ex.__class__.__name__.endswith('_Remote'):
# Some special case for locally re-raised remote exceptions
Secondly, if a remote exception is not from a module listed in the allowed_remote_exmods list, then a messaging.RemoteError exception is raised with all details of the remote exception.
Note: call is done ‘at-most-once’. In case of we can’t known if the call have been done correctly, because we didn’t get the response on time, MessagingTimeout exception is raised. The real reason can vary, transport failure, worker doesn’t answer in time or crash, ...
Parameters: |
|
---|---|
Raises: | MessagingTimeout, RemoteError, MessageDeliveryFailure |
Check to see if a version is compatible with the version cap.
Invoke a method and return immediately.
Method arguments must either be primitive types or types supported by the client’s serializer (if any).
Similarly, the request context must be a dict unless the client’s serializer supports serializing another type.
Note: cast does not ensure that the remote method will be executed on each destination. But it does ensure that the method will be not executed twice on a destination (e.g. ‘at-most-once’ execution).
Note: there are no ordering guarantees across successive casts, even among casts to the same destination. Therefore methods may be executed in an order different from the order in which they are cast.
Parameters: |
|
---|---|
Raises: | MessageDeliveryFailure |
Prepare a method invocation context.
Use this method to override client properties for an individual method invocation. For example:
def test(self, ctxt, arg):
cctxt = self.prepare(version='2.5')
return cctxt.call(ctxt, 'test', arg=arg)
Parameters: |
|
---|
Signifies that a remote endpoint method has raised an exception.
Contains a string representation of the type of the original exception, the value of the original exception, and the traceback. These are sent to the parent as a joined string so printing the exception contains all of the relevant info.