code: def cache_async(self, key_fn=_key_fn, timeout=3600):
          
          def decorator(fn):
              wrapped = self.cached(key_fn, timeout)(fn)
  
              @wraps(fn)
              def inner(*args, **kwargs):
                  q = Queue()
                  def _sub_fn():
                      q.put(wrapped(*args, **kwargs))
                  def _get_value(block=True, timeout=None):
                      if not hasattr(_get_value, '_return_value'):
                          result = q.get(block=block, timeout=timeout)
                          _get_value._return_value = result
                      return _get_value._return_value
  
                  thread = threading.Thread(target=_sub_fn)
                  thread.start()
                  return _get_value
              return inner
          return decorator
docs: Decorator that will execute the cached function in a separate
          thread. The function will immediately return, returning a
          callable to the user. This callable can be used to check for
          a return value.
  
          For details, see the :ref:`cache-async` section of the docs.
  
          :param key_fn: Function used to generate cache key.
          :param int timeout: Cache timeout in seconds.
          :returns: A new function which can be called to retrieve the
              return value of the decorated function.