issue #369: refactor ContextService to support reset().

issue260
David Wilson 6 years ago
parent 519faa3b3b
commit 9b7c958e2e

@ -146,6 +146,25 @@ class ContextService(mitogen.service.Service):
self._lru_by_via = {} self._lru_by_via = {}
#: :func:`key_from_dict` result by Context. #: :func:`key_from_dict` result by Context.
self._key_by_context = {} self._key_by_context = {}
#: Mapping of Context -> parent Context
self._via_by_context = {}
@mitogen.service.expose(mitogen.service.AllowParents())
@mitogen.service.arg_spec({
'context': mitogen.core.Context
})
def reset(self, context):
"""
Return a reference, forcing close and discard of the underlying
connection. Used for 'meta: reset_connection' or when some other error
is detected.
"""
LOG.debug('%r.reset(%r)', self, context)
self._lock.acquire()
try:
self._shutdown_unlocked(context)
finally:
self._lock.release()
@mitogen.service.expose(mitogen.service.AllowParents()) @mitogen.service.expose(mitogen.service.AllowParents())
@mitogen.service.arg_spec({ @mitogen.service.arg_spec({
@ -189,6 +208,19 @@ class ContextService(mitogen.service.Service):
self._lock.release() self._lock.release()
return count return count
def _forget_context_unlocked(self, context):
key = self._key_by_context.get(context)
if key is None:
LOG.debug('%r: attempt to forget unknown %r', self, context)
return
self._response_by_key.pop(key, None)
self._latches_by_key.pop(key, None)
self._key_by_context.pop(context, None)
self._refs_by_context.pop(context, None)
self._via_by_context.pop(context, None)
self._lru_by_via.pop(context, None)
def _shutdown_unlocked(self, context, lru=None, new_context=None): def _shutdown_unlocked(self, context, lru=None, new_context=None):
""" """
Arrange for `context` to be shut down, and optionally add `new_context` Arrange for `context` to be shut down, and optionally add `new_context`
@ -196,15 +228,15 @@ class ContextService(mitogen.service.Service):
""" """
LOG.info('%r._shutdown_unlocked(): shutting down %r', self, context) LOG.info('%r._shutdown_unlocked(): shutting down %r', self, context)
context.shutdown() context.shutdown()
via = self._via_by_context.get(context)
key = self._key_by_context[context] if via:
del self._response_by_key[key] lru = self._lru_by_via.get(via)
del self._refs_by_context[context] if lru:
del self._key_by_context[context] if context in lru:
if lru and context in lru:
lru.remove(context) lru.remove(context)
if new_context: if new_context:
lru.append(new_context) lru.append(new_context)
self._forget_context_unlocked(context)
def _update_lru_unlocked(self, new_context, spec, via): def _update_lru_unlocked(self, new_context, spec, via):
""" """
@ -225,6 +257,7 @@ class ContextService(mitogen.service.Service):
'but they are all marked as in-use.', via) 'but they are all marked as in-use.', via)
return return
self._via_by_context[new_context] = via
self._shutdown_unlocked(context, lru=lru, new_context=new_context) self._shutdown_unlocked(context, lru=lru, new_context=new_context)
def _update_lru(self, new_context, spec, via): def _update_lru(self, new_context, spec, via):
@ -243,7 +276,6 @@ class ContextService(mitogen.service.Service):
try: try:
for context in list(self._key_by_context): for context in list(self._key_by_context):
self._shutdown_unlocked(context) self._shutdown_unlocked(context)
self._lru_by_via = {}
finally: finally:
self._lock.release() self._lock.release()
@ -259,15 +291,11 @@ class ContextService(mitogen.service.Service):
self._lock.acquire() self._lock.acquire()
try: try:
routes = self.router.route_monitor.get_routes(stream) routes = self.router.route_monitor.get_routes(stream)
for context, key in list(self._key_by_context.items()): for context in list(self._key_by_context):
if context.context_id in routes: if context.context_id in routes:
LOG.info('Dropping %r due to disconnect of %r', LOG.info('Dropping %r due to disconnect of %r',
context, stream) context, stream)
self._response_by_key.pop(key, None) self._forget_context_unlocked(context)
self._latches_by_key.pop(key, None)
self._refs_by_context.pop(context, None)
self._lru_by_via.pop(context, None)
self._refs_by_context.pop(context, None)
finally: finally:
self._lock.release() self._lock.release()

Loading…
Cancel
Save