Issue 1:
First check

I added a very descriptive title to this issue.

I used the GitHub search to find a similar issue and didn't find it.

I searched the FastAPI documentation, with the integrated search.

I already searched in Google "How to X in FastAPI" and didn't find any information.

I already read and followed all the tutorial in the docs and didn't find an answer.

I already checked if it is not related to FastAPI but to Pydantic.

I already checked if it is not related to FastAPI but to Swagger UI.

I already checked if it is not related to FastAPI but to ReDoc.

After submitting this, I commit to one of:

Read open issues with questions until I find 2 issues where I can help someone and add a comment to help there.

I already hit the "watch" button in this repository to receive notifications and I commit to help at least 2 people that ask questions in the future.

Implement a Pull Request for a confirmed bug.

Example

I am not sure if I am able to create a minimal example, see description below.

Description

I have been using FastAPI for almost a year now without almost any issues, but I met one issue which is quite hard to reproduce and I might need your help.

My backend (simplified), consists of two parts: the API, and the worker. The API is run by gunicorn, and the worker is run separately, to avoid creating duplicate instances of background tasks. They are communicating between each other via redis.

What I have is, a background task that should mark an object (invoice) as expired after certain time.

What I did is an async function, that just does asyncio.sleep, and after that it marks invoice as expired in the database.

When invoice is created (from the API, via one of the workers gunicorn is serving), an asyncio task is created to mark invoice expired later.

Also, the background worker on startup checks pending invoices if they have expired.

Seems to be working fine even after server restarts.

But in very cases it doesn't work, I have checked server logs, and saw a few entries with "[CRITICAL] Worker timeout"

So as far as I understand, from time to time the workers time out and get restarted, so all started async tasks are lost.

It happens quite rarely, for now 3 times: on January 4th, 10th and 17th, and every time multiple workers get restarted or get restarted multiple times.

All my functions are async, and I am not sure what exactly might cause the timeout if all the long-running functions are delegated to the worker.

Attaching screenshots, and all the code is available at github too.

I am sorry that I am unable to provide a simple example, because the project is complex, and I think that I don't have any long-running tasks in the gunicorn process (proper distribution of tasks, this system has been working great on many systems, including the demo which is running without any issues except for this for 1 month already).

I think that the issue might be just my gunicorn configuration, which is the default one almost.

I understand that it might be hard to investigate the issue, so I am ready to provide all needed details and answer all the following questions in detail. I was directed here from discord.

Environment

OS: Linux; Docker environment with docker-compose; Custom setup:

backend component

worker component

Dockerfile

FastAPI Version: 0.63.0

Python version: 3.6.12

Additional context

The function running as an async task:

Server logs:

How the task is started:

Gunicorn config:

import multiprocessing

bind = "0.0.0.0:8000"
workers = multiprocessing.cpu_count() * 2 + 1
worker_class = "uvicorn.workers.UvicornWorker"

Backend startup script:

#!/usr/bin/env sh
set -ex
alembic upgrade head
gunicorn -c gunicorn.conf.py main:app

Entrypoint

Repository

Issue 2:
First check

I added a very descriptive title to this issue.

I used the GitHub search to find a similar issue and didn't find it.

I searched the FastAPI documentation, with the integrated search.

I already searched in Google "How to X in FastAPI" and didn't find any information.

I already read and followed all the tutorial in the docs and didn't find an answer.

I already checked if it is not related to FastAPI but to Pydantic.

I already checked if it is not related to FastAPI but to Swagger UI.

I already checked if it is not related to FastAPI but to ReDoc.

After submitting this, I commit to one of:

Read open issues with questions until I find 2 issues where I can help someone and add a comment to help there.

I already hit the "watch" button in this repository to receive notifications and I commit to help at least 2 people that ask questions in the future.

Implement a Pull Request for a confirmed bug.

Example

Here's a self-contained, minimal, reproducible, example with my use case:

from fastapi import WebSocket, Depends, FastAPI
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
from starlette.testclient import TestClient

app = FastAPI()

@app.websocket('/')
async def socket(
websocket: WebSocket,
bearer_token: HTTPAuthorizationCredentials = Depends(HTTPBearer())
):
await websocket.accept()
await websocket.send_text("hello there")
await websocket.close()

def test_socket():
client = TestClient(app)
with client.websocket_connect("/") as ws:
ws.read_text()
ws.close()

Description

Adding any dependency that requires additional parameters makes this endpoint crash with a TypeError __call__() missing 1 required positional argument: 'request' when used from the TestClient.

It works fine when running with uvicorn.

Traceback:

test_websocket_depends.py:17 (test_socket)
def test_socket():
client = TestClient(app)
> with client.websocket_connect("/") as ws:

test_websocket_depends.py:20:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
../../venv/lib64/python3.8/site-packages/starlette/testclient.py:444: in websocket_connect
super().request("GET", url, **kwargs)
../../venv/lib64/python3.8/site-packages/requests/sessions.py:530: in request
resp = self.send(prep, **send_kwargs)
../../venv/lib64/python3.8/site-packages/requests/sessions.py:643: in send
r = adapter.send(request, **kwargs)
../../venv/lib64/python3.8/site-packages/starlette/testclient.py:145: in send
session = WebSocketTestSession(self.app, scope)
../../venv/lib64/python3.8/site-packages/starlette/testclient.py:277: in __init__
message = self.receive()
../../venv/lib64/python3.8/site-packages/starlette/testclient.py:339: in receive
raise message
../../venv/lib64/python3.8/site-packages/starlette/testclient.py:300: in _run
self._loop.run_until_complete(self.app(scope, receive, send))
/usr/lib64/python3.8/asyncio/base_events.py:616: in run_until_complete
return future.result()
../../venv/lib64/python3.8/site-packages/fastapi/applications.py:179: in __call__
await super().__call__(scope, receive, send)
../../venv/lib64/python3.8/site-packages/starlette/applications.py:111: in __call__
await self.middleware_stack(scope, receive, send)
../../venv/lib64/python3.8/site-packages/starlette/middleware/errors.py:146: in __call__
await self.app(scope, receive, send)
../../venv/lib64/python3.8/site-packages/starlette/exceptions.py:58: in __call__
await self.app(scope, receive, send)
../../venv/lib64/python3.8/site-packages/starlette/routing.py:566: in __call__
await route.handle(scope, receive, send)
../../venv/lib64/python3.8/site-packages/starlette/routing.py:283: in handle
await self.app(scope, receive, send)
../../venv/lib64/python3.8/site-packages/starlette/routing.py:57: in app
await func(session)
../../venv/lib64/python3.8/site-packages/fastapi/routing.py:218: in app
solved_result = await solve_dependencies(
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

async def solve_dependencies(
*,
request: Union[Request, WebSocket],
dependant: Dependant,
body: Optional[Union[Dict[str, Any], FormData]] = None,
background_tasks: Optional[BackgroundTasks] = None,
response: Optional[Response] = None,
dependency_overrides_provider: Optional[Any] = None,
dependency_cache: Optional[Dict[Tuple[Callable, Tuple[str]], Any]] = None,
) -> Tuple[
Dict[str, Any],
List[ErrorWrapper],
Optional[BackgroundTasks],
Response,
Dict[Tuple[Callable, Tuple[str]], Any],
]:
values: Dict[str, Any] = {}
errors: List[ErrorWrapper] = []
response = response or Response(
content=None,
status_code=None, # type: ignore
headers=None,
media_type=None,
background=None,
)
dependency_cache = dependency_cache or {}
sub_dependant: Dependant
for sub_dependant in dependant.dependencies:
sub_dependant.call = cast(Callable, sub_dependant.call)
sub_dependant.cache_key = cast(
Tuple[Callable, Tuple[str]], sub_dependant.cache_key
)
call = sub_dependant.call
use_sub_dependant = sub_dependant
if (
dependency_overrides_provider
and dependency_overrides_provider.dependency_overrides
):
original_call = sub_dependant.call
call = getattr(
dependency_overrides_provider, "dependency_overrides", {}
).get(original_call, original_call)
use_path: str = sub_dependant.path # type: ignore
use_sub_dependant = get_dependant(
path=use_path,
call=call,
name=sub_dependant.name,
security_scopes=sub_dependant.security_scopes,
)
use_sub_dependant.security_scopes = sub_dependant.security_scopes

solved_result = await solve_dependencies(
request=request,
dependant=use_sub_dependant,
body=body,
background_tasks=background_tasks,
response=response,
dependency_overrides_provider=dependency_overrides_provider,
dependency_cache=dependency_cache,
)
(
sub_values,
sub_errors,
background_tasks,
_, # the subdependency returns the same response we have
sub_dependency_cache,
) = solved_result
dependency_cache.update(sub_dependency_cache)
if sub_errors:
errors.extend(sub_errors)
continue
if sub_dependant.use_cache and sub_dependant.cache_key in dependency_cache:
solved = dependency_cache[sub_dependant.cache_key]
elif is_gen_callable(call) or is_async_gen_callable(call):
stack = request.scope.get("fastapi_astack")
if stack is None:
raise RuntimeError(
async_contextmanager_dependencies_error
) # pragma: no cover
solved = await solve_generator(
call=call, stack=stack, sub_values=sub_values
)
elif is_coroutine_callable(call):
> solved = await call(**sub_values)
E TypeError: __call__() missing 1 required positional argument: 'request'

../../venv/lib64/python3.8/site-packages/fastapi/dependencies/utils.py:550: TypeError

Environment

OS: [e.g. Linux / Windows / macOS]: Fedora 32

FastAPI Version [e.g. 0.3.0]: 0.61.1

Python version: Python 3.8.5