issue #535: service: support Pool.defer() like Broker.defer()

pull/564/head
David Wilson 5 years ago
parent eb9ec26622
commit 514d35fd10

@ -411,10 +411,12 @@ class Service(object):
def __repr__(self):
return '%s()' % (self.__class__.__name__,)
def on_message(self, recv, msg):
def on_message(self, event):
"""
Called when a message arrives on any of :attr:`select`'s registered
receivers.
:param mitogen.select.Event event:
"""
pass
@ -452,6 +454,7 @@ class Pool(object):
def __init__(self, router, services, size=1, overwrite=False):
self.router = router
self._activator = self.activator_class()
self._ipc_latch = mitogen.core.Latch()
self._receiver = mitogen.core.Receiver(
router=router,
handle=mitogen.core.CALL_SERVICE,
@ -460,9 +463,13 @@ class Pool(object):
self._select = mitogen.select.Select(oneshot=False)
self._select.add(self._receiver)
self._select.add(self._ipc_latch)
#: Serialize service construction.
self._lock = threading.Lock()
self._func_by_recv = {self._receiver: self._on_service_call}
self._func_by_source = {
self._receiver: self._on_service_call,
self._ipc_latch: self._on_ipc_latch,
}
self._invoker_by_name = {}
for service in services:
@ -488,10 +495,10 @@ class Pool(object):
name = service.name()
if name in self._invoker_by_name:
raise Error('service named %r already registered' % (name,))
assert service.select not in self._func_by_recv
assert service.select not in self._func_by_source
invoker = service.invoker_class(service=service)
self._invoker_by_name[name] = invoker
self._func_by_recv[service.select] = service.on_message
self._func_by_source[service.select] = service.on_message
closed = False
@ -534,7 +541,18 @@ class Pool(object):
isinstance(tup[2], dict)):
raise mitogen.core.CallError('Invalid message format.')
def _on_service_call(self, recv, msg):
def defer(self, func, *args, **kwargs):
"""
Arrange for `func(*args, **kwargs)` to be invoked in the context of a
service pool thread.
"""
self._ipc_latch.put(lambda: func(*args, **kwargs))
def _on_ipc_latch(self, event):
event.data()
def _on_service_call(self, event):
msg = event.data
service_name = None
method_name = None
try:
@ -555,17 +573,17 @@ class Pool(object):
def _worker_run(self):
while not self.closed:
try:
msg = self._select.get()
event = self._select.get_event()
except (mitogen.core.ChannelError, mitogen.core.LatchError):
e = sys.exc_info()[1]
LOG.debug('%r: channel or latch closed, exitting: %s', self, e)
return
func = self._func_by_recv[msg.receiver]
func = self._func_by_source[event.source]
try:
func(msg.receiver, msg)
func(event)
except Exception:
LOG.exception('While handling %r using %r', msg, func)
LOG.exception('While handling %r using %r', event.data, func)
def _worker_main(self):
try:

Loading…
Cancel
Save