title: Caching results in an async environment
body: <p>I am working in a FastAPI endpoint that make a I/O bound operation, which is async for efficiency. However, it takes time, so I would like to cache the results to reuse it for a period of time.</p>
  <p>I currently I have this:</p>
  <pre class="lang-py prettyprint-override"><code>from fastapi import FastAPI
  import asyncio
  
  app = FastAPI()
  
  async def _get_expensive_resource(key) -&gt; None:
      await asyncio.sleep(2)
      return True
  
  @app.get('/')
  async def get(key):
      return await _get_expensive_resource(key)
  
  if __name__ == &quot;__main__&quot;:
      import uvicorn
      uvicorn.run(&quot;test:app&quot;)
  </code></pre>
  <p>I am trying to use the <code>cachetools</code> package to cache the results and I have tried something like the following:</p>
  <pre class="lang-py prettyprint-override"><code>import asyncio
  from cachetools import TTLCache
  from fastapi import FastAPI
    
  app = FastAPI()
  
  async def _get_expensive_resource(key) -&gt; None:
      await asyncio.sleep(2)
      return True
  
  class ResourceCache(TTLCache):
      def __missing__(self, key):
          loop = asyncio.get_event_loop()
          resource = loop.run_until_complete(_get_expensive_resource(key))
          self[key] = resource
          return resource
  
  resource_cache = ResourceCache(124, 300)
  
  @app.get('/')
  async def get(key: str):
      return resource_cache[key]
  
  if __name__ == &quot;__main__&quot;:
      import uvicorn
      uvicorn.run(&quot;test2:app&quot;)
  </code></pre>
  <p>However, this fails, because, as far as I understand, the <code>__missing__</code> method is sync and you can't call async from sync from async. The error is:</p>
  <pre><code>RuntimeError: this event loop is already running.
  </code></pre>
  <p>Similar error happen if I use plain asyncio instead of uvloop.</p>
  <p>For the asyncio event loop, I have tried using <code>nest_asyncio</code> package, but it does not patch <code>uvloop</code> and also, even when using it with asyncio, it seems like the service freezes after using it the first time.</p>
  <p>Do you have any idea how could I acomplish this?</p>