I have a small fastapi example here
# run.py
from functools import cache
import uvicorn
from fastapi import FastAPI, Depends
app = FastAPI()
class Dep:
def __init__(self, inp):
self.inp = inp
@cache
def __call__(self):
print(self.inp * 100)
return self.inp
@app.get("/a")
def a(v: str = Depends(Dep("a"))):
return v
@app.get("/a/a")
def aa(v: str = Depends(Dep("a"))):
return v
@app.get("/b")
def b(v: str = Depends(Dep("b"))):
return v
@app.get("/b/b")
def bb(v: str = Depends(Dep("b"))):
return v
def main():
uvicorn.run(
"run:app",
host="0.0.0.0",
reload=True,
port=8000,
workers=1
)
if __name__ == "__main__":
main()
I run python run.py
and the application spins up.
What I expect is that:
the first time I hit /a
or /a/a
endpoints it shows logs to me and print 100 "a" for me. the next times no logging happens because of the @cache
decorator
and
the first time I hit /b
or /b/b
endpoints it shows logs to me and print 100 "b"s for me. the next times no logging happens because of the @cache
decorator
What happens
The first time I hit /b
, it shows logs. the next times no log
The first time I hit /b/b
, it shows logs. the next times no log
The first time I hit /a
, it shows logs. the next times no log
The first time I hit /a/a
, it shows logs. the next times no log
the reason is that each time I am passing a value to the Dep class it is creating a new object and the call method is that of a new object each time. that is why the caching is not working properly.
and the caching is being done by fastapi dependency . That is why when I call an endpoint for the next times, I do not see new logs
But the question is how do I
- pass arguments to the callable dependency (a class)
- and also cache the value the function returns
Extra information
I tried to achieve the same using the approach below:
# run.py
from functools import cache
import uvicorn
from fastapi import FastAPI, Depends, Request
app = FastAPI()
@cache
def dep(inp):
@cache
def sub_dep():
print(inp*100)
return inp
return sub_dep
@app.get("/a")
def a(v: str = Depends(dep("a"))):
return v
@app.get("/a/a")
def aa(v: str = Depends(dep("a"))):
return v
@app.get("/b")
def b(v: str = Depends(dep("b"))):
return v
@app.get("/b/b")
def bb(v: str = Depends(dep("b"))):
return v
def main():
uvicorn.run(
"run:app",
host="0.0.0.0",
reload=True,
port=8000,
workers=1
)
if __name__ == "__main__":
main()
and it working as expected above