pc_rpc/Server: add built-in terminate

This commit is contained in:
Sebastien Bourdeauducq 2015-08-09 20:40:15 +08:00
parent a21049d779
commit 4b195663f6
1 changed files with 26 additions and 9 deletions

View File

@ -240,7 +240,8 @@ class BestEffortClient:
network errors are suppressed and connections are retried in the network errors are suppressed and connections are retried in the
background. background.
RPC calls that failed because of network errors return ``None``. RPC calls that failed because of network errors return ``None``. Other RPC
calls are blocking and return the correct value.
:param firstcon_timeout: Timeout to use during the first (blocking) :param firstcon_timeout: Timeout to use during the first (blocking)
connection attempt at object initialization. connection attempt at object initialization.
@ -397,12 +398,19 @@ class Server(_AsyncioServer):
exposed to the client. Keys are names identifying each object. exposed to the client. Keys are names identifying each object.
Clients select one of these objects using its name upon connection. Clients select one of these objects using its name upon connection.
:param id_parameters: An optional human-readable string giving more :param id_parameters: An optional human-readable string giving more
information about the parameters of the server. information about the server.
:param builtin_terminate: If set, the server provides a built-in
``terminate`` method that unblocks any tasks waiting on
``wait_terminate``. This is useful to handle server termination
requests from clients.
""" """
def __init__(self, targets, id_parameters=None): def __init__(self, targets, id_parameters=None, builtin_terminate=False):
_AsyncioServer.__init__(self) _AsyncioServer.__init__(self)
self.targets = targets self.targets = targets
self.id_parameters = id_parameters self.id_parameters = id_parameters
self.builtin_terminate = builtin_terminate
if builtin_terminate:
self._terminate_request = asyncio.Event()
@asyncio.coroutine @asyncio.coroutine
def _handle_connection_cr(self, reader, writer): def _handle_connection_cr(self, reader, writer):
@ -448,9 +456,13 @@ class Server(_AsyncioServer):
obj = {"status": "ok", "ret": doc} obj = {"status": "ok", "ret": doc}
elif obj["action"] == "call": elif obj["action"] == "call":
logger.debug("calling %s", _PrettyPrintCall(obj)) logger.debug("calling %s", _PrettyPrintCall(obj))
method = getattr(target, obj["name"]) if self.builtin_terminate and obj["name"] == "terminate":
ret = method(*obj["args"], **obj["kwargs"]) self._terminate_request.set()
obj = {"status": "ok", "ret": ret} obj = {"status": "ok", "ret": None}
else:
method = getattr(target, obj["name"])
ret = method(*obj["args"], **obj["kwargs"])
obj = {"status": "ok", "ret": ret}
else: else:
raise ValueError("Unknown action: {}" raise ValueError("Unknown action: {}"
.format(obj["action"])) .format(obj["action"]))
@ -462,18 +474,23 @@ class Server(_AsyncioServer):
finally: finally:
writer.close() writer.close()
@asyncio.coroutine
def wait_terminate(self):
yield from self._terminate_request.wait()
def simple_server_loop(targets, host, port, id_parameters=None): def simple_server_loop(targets, host, port, id_parameters=None):
"""Runs a server until an exception is raised (e.g. the user hits Ctrl-C). """Runs a server until an exception is raised (e.g. the user hits Ctrl-C)
or termination is requested by a client.
See ``Server`` for a description of the parameters. See ``Server`` for a description of the parameters.
""" """
loop = asyncio.get_event_loop() loop = asyncio.get_event_loop()
try: try:
server = Server(targets, id_parameters) server = Server(targets, id_parameters, True)
loop.run_until_complete(server.start(host, port)) loop.run_until_complete(server.start(host, port))
try: try:
loop.run_forever() loop.run_until_complete(server.wait_terminate())
finally: finally:
loop.run_until_complete(server.stop()) loop.run_until_complete(server.stop())
finally: finally: