diff --git a/examples/main.py b/examples/main.py index 466f13e..66e8bfc 100644 --- a/examples/main.py +++ b/examples/main.py @@ -1,4 +1,5 @@ from datetime import date, datetime +import time import redis.asyncio as redis import uvicorn @@ -40,6 +41,13 @@ async def get_data(request: Request, response: Response): return date.today() +@app.get("/blocking") +@cache(namespace="test", expire=20) +def blocking(request: Request, response: Response): + time.sleep(5) + return dict(ret=get_ret()) + + @app.get("/datetime") @cache(namespace="test", expire=20) async def get_datetime(request: Request, response: Response): diff --git a/fastapi_cache/decorator.py b/fastapi_cache/decorator.py index 7b60408..ed1a30c 100644 --- a/fastapi_cache/decorator.py +++ b/fastapi_cache/decorator.py @@ -1,15 +1,21 @@ -from functools import wraps -from typing import Callable, Optional, Type +import asyncio +from functools import wraps, partial +import inspect +from typing import TYPE_CHECKING, Callable, Optional, Type from fastapi_cache import FastAPICache from fastapi_cache.coder import Coder +if TYPE_CHECKING: + import concurrent.futures + def cache( expire: int = None, coder: Type[Coder] = None, key_builder: Callable = None, namespace: Optional[str] = "", + executor: Optional["concurrent.futures.Executor"] = None, ): """ cache all function @@ -17,6 +23,8 @@ def cache( :param expire: :param coder: :param key_builder: + :param executor: + :return: """ @@ -63,7 +71,12 @@ def cache( response.headers["ETag"] = etag return coder.decode(ret) - ret = await func(*args, **kwargs) + if inspect.iscoroutinefunction(func): + ret = await func(*args, **kwargs) + else: + loop = asyncio.get_event_loop() + ret = await loop.run_in_executor(executor, partial(func, *args, **kwargs)) + await backend.set(cache_key, coder.encode(ret), expire or FastAPICache.get_expire()) return ret