Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix error in fastapi example #51

Open
realimpat opened this issue Nov 9, 2024 · 0 comments
Open

Fix error in fastapi example #51

realimpat opened this issue Nov 9, 2024 · 0 comments

Comments

@realimpat
Copy link

There's an error in the api.py file in the fastapi.

Here's the error:

 in Onboarding Flow' - Created task run 'Enroll [email protected] in Onboarding Flow' for task 'enroll_in_onboarding_flow'
api-1        | 22:30:45.656 | INFO    | prefect.tasks - Created task run 'populate_workspace'. View it in the UI at 'http://prefect:4200/runs/task-run/1a76e005-c48d-45d3-84a8-a6e23c4de347'
api-1        | Exception in ASGI application
api-1        | Traceback (most recent call last):
api-1        |   File "/usr/local/lib/python3.12/site-packages/uvicorn/protocols/http/h11_impl.py", line 412, in run_asgi
api-1        |     result = await app(  # type: ignore[func-returns-value]
api-1        |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
api-1        |   File "/usr/local/lib/python3.12/site-packages/uvicorn/middleware/proxy_headers.py", line 84, in __call__
api-1        |     return await self.app(scope, receive, send)
api-1        |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
api-1        |   File "/usr/local/lib/python3.12/site-packages/fastapi/applications.py", line 1054, in __call__
api-1        |     await super().__call__(scope, receive, send)
api-1        |   File "/usr/local/lib/python3.12/site-packages/starlette/applications.py", line 123, in __call__
api-1        |     await self.middleware_stack(scope, receive, send)
api-1        |   File "/usr/local/lib/python3.12/site-packages/starlette/middleware/errors.py", line 186, in __call__
api-1        |     raise exc
api-1        |   File "/usr/local/lib/python3.12/site-packages/starlette/middleware/errors.py", line 164, in __call__
api-1        |     await self.app(scope, receive, _send)
api-1        |   File "/usr/local/lib/python3.12/site-packages/starlette/middleware/exceptions.py", line 65, in __call__
api-1        |     await wrap_app_handling_exceptions(self.app, conn)(scope, receive, send)
api-1        |   File "/usr/local/lib/python3.12/site-packages/starlette/_exception_handler.py", line 64, in wrapped_app
api-1        |     raise exc
api-1        |   File "/usr/local/lib/python3.12/site-packages/starlette/_exception_handler.py", line 53, in wrapped_app
api-1        |     await app(scope, receive, sender)
api-1        |   File "/usr/local/lib/python3.12/site-packages/starlette/routing.py", line 754, in __call__
api-1        |     await self.middleware_stack(scope, receive, send)
api-1        |   File "/usr/local/lib/python3.12/site-packages/starlette/routing.py", line 774, in app
api-1        |     await route.handle(scope, receive, send)
api-1        |   File "/usr/local/lib/python3.12/site-packages/starlette/routing.py", line 295, in handle
api-1        |     await self.app(scope, receive, send)
api-1        |   File "/usr/local/lib/python3.12/site-packages/starlette/routing.py", line 77, in app
api-1        |     await wrap_app_handling_exceptions(app, request)(scope, receive, send)
api-1        |   File "/usr/local/lib/python3.12/site-packages/starlette/_exception_handler.py", line 64, in wrapped_app
api-1        |     raise exc
api-1        |   File "/usr/local/lib/python3.12/site-packages/starlette/_exception_handler.py", line 53, in wrapped_app
api-1        |     await app(scope, receive, sender)
api-1        |   File "/usr/local/lib/python3.12/site-packages/starlette/routing.py", line 74, in app
api-1        |     response = await f(request)
api-1        |                ^^^^^^^^^^^^^^^^
api-1        |   File "/usr/local/lib/python3.12/site-packages/fastapi/routing.py", line 297, in app
api-1        |     raw_response = await run_endpoint_function(
api-1        |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
api-1        |   File "/usr/local/lib/python3.12/site-packages/fastapi/routing.py", line 210, in run_endpoint_function
api-1        |     return await dependant.call(**values)
api-1        |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
api-1        |   File "/app/fastapi_user_signups/api.py", line 21, in create_user
api-1        |     await asyncio.gather(
api-1        |           ^^^^^^^^^^^^^^^
api-1        |   File "/usr/local/lib/python3.12/asyncio/tasks.py", line 831, in gather
api-1        |     fut = ensure_future(arg, loop=loop)
api-1        |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
api-1        |   File "/usr/local/lib/python3.12/asyncio/tasks.py", line 689, in ensure_future
api-1        |     raise TypeError('An asyncio.Future, a coroutine or an awaitable '
api-1        | TypeError: 

Here's an explanation.

The error occurs because tasks.send_confirmation_email.delay() (and the other task delays) don't return coroutines that can be awaited.

In Prefect, the .delay() method is used to schedule a task for execution, but it's not meant to be awaited. You're trying to use asyncio.gather() with these non-awaitable task schedules.

Here's how to fix the code:

@app.post("/users", status_code=201)
async def create_user(new_user: NewUser) -> User:
    user = await models.create_user(new_user)

    # Don't await these - they're fire-and-forget tasks
    tasks.send_confirmation_email.delay(user)
    tasks.enroll_in_onboarding_flow.delay(user)
    tasks.populate_workspace.delay(user)

    return user

The key changes:

  1. Removed the asyncio.gather() since it's not needed
  2. Simply call .delay() on each task without awaiting them

This matches the intention described in the README:

These are fire-and-forget tasks that need to happen, but the request cycle doesn't need
to wait on them to complete.

The tasks are meant to be "fire-and-forget" - they should be queued up to run asynchronously without the API request waiting for them to complete.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant