diff --git a/ansible_mitogen/services.py b/ansible_mitogen/services.py index eae8fc68..f9a1a3df 100644 --- a/ansible_mitogen/services.py +++ b/ansible_mitogen/services.py @@ -89,6 +89,24 @@ def _get_candidate_temp_dirs(): return mitogen.utils.cast(dirs) +def key_from_dict(**kwargs): + """ + Return a unique string representation of a dict as quickly as possible. + Used to generated deduplication keys from a request. + """ + out = [] + stack = [kwargs] + while stack: + obj = stack.pop() + if isinstance(obj, dict): + stack.extend(sorted(obj.items())) + elif isinstance(obj, (list, tuple)): + stack.extend(obj) + else: + out.append(str(obj)) + return ''.join(out) + + class Error(Exception): pass @@ -113,7 +131,7 @@ class ContextService(mitogen.service.Service): super(ContextService, self).__init__(*args, **kwargs) self._lock = threading.Lock() #: Records the :meth:`get` result dict for successful calls, returned - #: for identical subsequent calls. Keyed by :meth:`key_from_kwargs`. + #: for identical subsequent calls. Keyed by :meth:`key_from_dict`. self._response_by_key = {} #: List of :class:`mitogen.core.Latch` awaiting the result for a #: particular key. @@ -126,7 +144,7 @@ class ContextService(mitogen.service.Service): #: :attr:`max_interpreters` is reached, the most recently used context #: is destroyed to make room for any additional context. self._lru_by_via = {} - #: :meth:`key_from_kwargs` result by Context. + #: :func:`key_from_dict` result by Context. self._key_by_context = {} @mitogen.service.expose(mitogen.service.AllowParents()) @@ -149,29 +167,13 @@ class ContextService(mitogen.service.Service): finally: self._lock.release() - def key_from_kwargs(self, **kwargs): - """ - Generate a deduplication key from the request. - """ - out = [] - stack = [kwargs] - while stack: - obj = stack.pop() - if isinstance(obj, dict): - stack.extend(sorted(obj.items())) - elif isinstance(obj, (list, tuple)): - stack.extend(obj) - else: - out.append(str(obj)) - return ''.join(out) - def _produce_response(self, key, response): """ Reply to every waiting request matching a configuration key with a response dictionary, deleting the list of waiters when done. :param str key: - Result of :meth:`key_from_kwargs` + Result of :meth:`key_from_dict` :param dict response: Response dictionary :returns: @@ -361,7 +363,7 @@ class ContextService(mitogen.service.Service): def _wait_or_start(self, spec, via=None): latch = mitogen.core.Latch() - key = self.key_from_kwargs(via=via, **spec) + key = key_from_dict(via=via, **spec) self._lock.acquire() try: response = self._response_by_key.get(key)