Remote Method InvocationΒΆ

On top of bnd.net a small module is layered which allows for remote method invocation. It’s fairly simple, any not otherwise resolvable attribute on an RMIPeerNode object is considered a remote method. When called the name of the member and the arguments of the call are sent to the other node, the member is ‘resolved’ through getattr(self, name) and then invoked with the *args** and **kwargs of the call.

Obviously the member should exist on the RMINode bndl.rmi.node.RMINode receiving the invocation. To execute arbitrary functions on the remote node run worker/driver nodes in the cluster from the bndl.compute or bndl.execute modules; e.g. by running the bndl-compute-shell or bndl-compute-workers commands. Such nodes provide the execute(...)` method, e.g.:

>>> from bndl.compute.run import ctx
>>> ctx.await_workers()
4
>>> ctx.workers[0].execute(lambda: 42).result()
42

Invoking a remote method returns a concurrent.futures.Future. Call .result() on it the get the response. Use .with_timeout(n) to wait at most n seconds for a response. A concurrent.futures.TimeoutError will be raised if that happens:

>>> ctx.workers[0].execute.with_timeout(1)(lambda: 42).result()
42
>>> ctx.workers[0].execute.with_timeout(0)(lambda: 42).result()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/frens-jan/Workspaces/ext/cpython3.5/Lib/concurrent/futures/_base.py", line 405, in result
    return self.__get_result()
  File "/home/frens-jan/Workspaces/ext/cpython3.5/Lib/concurrent/futures/_base.py", line 357, in __get_result
    raise self._exception
2016-12-05 00:33:51,068 - bndl.rmi.node -  WARNING - Response <Response exception=None, req_id=1, value=42> received for unknown request id 1
  File "/home/frens-jan/Workspaces/tgho/bndl/bndl/bndl/util/aio.py", line 64, in task_done
    future.set_result(task.result())
  File "/home/frens-jan/Workspaces/ext/cpython3.5/Lib/asyncio/futures.py", line 292, in result
    raise self._exception
  File "/home/frens-jan/Workspaces/ext/cpython3.5/Lib/asyncio/tasks.py", line 239, in _step
    result = coro.send(None)
  File "/home/frens-jan/Workspaces/tgho/bndl/bndl/bndl/rmi/node.py", line 58, in _request
    response = (yield from asyncio.wait_for(response_future, self._timeout, loop=self.peer.loop))
  File "/home/frens-jan/Workspaces/ext/cpython3.5/Lib/asyncio/tasks.py", line 404, in wait_for
    raise futures.TimeoutError()
concurrent.futures._base.TimeoutError