sync dependency on async router, how does this work? #11991
-
First Check
Commit to Help
Example Codedef users_repository() -> Users:
raise NotImplementedError("Override this dependency with a concrete implementation")
def user_factory() -> User:
raise NotImplementedError("Override this dependency with a concrete implementation")
router = APIRouter()
@router.post("/users", response_model=UserResponse)
async def create_user(user: User = Depends(user_factory), users: Users = Depends(users_repository)):
try:
await users.add(user)
return user
except exceptions.UserAlreadyExists:
raise HTTPException(status_code=status.HTTP_409_CONFLICT, detail="User already exists")
except Exception:
raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail="Internal server error")DescriptionFor example in the code, I'm using dependency injection a lot for decoupling my domain layer and my controller layer, like the example code, I have a users repository and a user aggregate factory, that will be injected later in the code, and I have a a questions regarding this. Is it okay to override sync dependencies with async ones? Does fastapi add sync dependencies in executor mode from asyncio or it just plain use them? I don't want to be adding a lot of threads simply for just creating a domain object or something is not a heavy cpu task, but also don't want to lock my code with sync dependencies, for example here: async def hash_credential(form: OAuth2PasswordRequestForm = Depends(), security: Security = Depends(security_service)) -> Credential:
loop = get_event_loop()
hashed_password = await loop.run_in_executor(security.hash, form.password)
return Credential(username=form.username, password=hashed_password)
@router.post("/users/{id}/credentials", response_model=UserResponse)
async def add_credentials(id: UUID, credential: Credential = Depends(hash_credential), users: Users = Depends(users_repository)):
user = await users.get_by_id(id)
if not user:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="User not found")
await users.credentials.add(credential, user)
return userI need the passwords to be hashed before it even touch the backend because, one can't really trust other people working on something, hashing the password is a heavy CPU task so it must be added to a run in executor mode from asyncio, but I was having dobouts if I have a sync dependency like that, will it be added into the code in executor mode? or will be just used without asyncio? Operating SystemLinux Operating System DetailsNo response FastAPI Version0.112.0 Pydantic Version2.8.2 Python VersionPython 3.12.3 Additional ContextNo response |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 1 reply
-
There is no problem with that. FastAPI will see that this function is
Sync dependencies will be executed in separate thread and will not block the event loop. If your dependency function is not a heavy CPU task, just use |
Beta Was this translation helpful? Give feedback.
There is no problem with that. FastAPI will see that this function is
syncand run it in the thread_pool.Sync dependencies will be executed in separate thread and will not block the event loop.
If your dependency function is not a heavy CPU task, just use
asyncto define it