Add support for normal def functions

This commit is contained in:
Jegor Kitskerkin
2022-08-01 00:04:10 +02:00
parent 8c92cc59ae
commit d6c52408d2
2 changed files with 24 additions and 3 deletions

View File

@@ -1,4 +1,5 @@
from datetime import date, datetime from datetime import date, datetime
import time
import redis.asyncio as redis import redis.asyncio as redis
import uvicorn import uvicorn
@@ -40,6 +41,13 @@ async def get_data(request: Request, response: Response):
return date.today() 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") @app.get("/datetime")
@cache(namespace="test", expire=20) @cache(namespace="test", expire=20)
async def get_datetime(request: Request, response: Response): async def get_datetime(request: Request, response: Response):

View File

@@ -1,15 +1,21 @@
from functools import wraps import asyncio
from typing import Callable, Optional, Type from functools import wraps, partial
import inspect
from typing import TYPE_CHECKING, Callable, Optional, Type
from fastapi_cache import FastAPICache from fastapi_cache import FastAPICache
from fastapi_cache.coder import Coder from fastapi_cache.coder import Coder
if TYPE_CHECKING:
import concurrent.futures
def cache( def cache(
expire: int = None, expire: int = None,
coder: Type[Coder] = None, coder: Type[Coder] = None,
key_builder: Callable = None, key_builder: Callable = None,
namespace: Optional[str] = "", namespace: Optional[str] = "",
executor: Optional["concurrent.futures.Executor"] = None,
): ):
""" """
cache all function cache all function
@@ -17,6 +23,8 @@ def cache(
:param expire: :param expire:
:param coder: :param coder:
:param key_builder: :param key_builder:
:param executor:
:return: :return:
""" """
@@ -63,7 +71,12 @@ def cache(
response.headers["ETag"] = etag response.headers["ETag"] = etag
return coder.decode(ret) 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()) await backend.set(cache_key, coder.encode(ret), expire or FastAPICache.get_expire())
return ret return ret