Skip to content

feat: Add support for async functions #364

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

Open
wants to merge 4 commits into
base: main
Choose a base branch
from

Conversation

taeold
Copy link

@taeold taeold commented Apr 7, 2025

This pull request introduces foundational support for defining and running Google Cloud Functions using Python's native async/await syntax within the Functions Framework. This allows developers to leverage the asynchronous ecosystem for I/O-bound operations directly in their function code.

For example, developers can now write:

import asyncio

import functions_framework.aio

@functions_framework.aio.http
async def hello_async(request): # Starlette.Request
  """An example async HTTP function."""
  await asyncio.sleep(1)
  return "Hello, async world!"

The framework handles bootstrapping an ASGI server using Starlette to host and execute these asynchronous function targets, analogous to how Flask is used for existing WSGI functions.

Key Changes:

  • New functions_framework.aio Submodule: Introduced a dedicated submodule to house asynchronous-specific components, keeping implementation separated from the existing WSGI implementation.

  • create_asgi_app: async version of create_app to bootstrap an asynchronous function target and wraps it into a Starlette ASGI application, handling request parsing and response formatting.

  • Optional Dependency ([async] extra): Starlette and its dependencies (uvicorn likely needed later) are introduced as optional packages for functions_framework. Users must explicitly install the framework with the async extra to enable this functionality to avoid adding unnecessary dependencies for users who existing "synch"-only use cases.

$ pip install functions_framework[async]

The structure and internal handling within create_asgi_app attempt to mirror the existing WSGI implementation where feasible, aiming for consistency in request processing logic (e.g., header handling, response serialization).

Explicitly Out of Scope (for this PR):

This PR is the first step towards full async support. Several key pieces are intentionally omitted and will be addressed in subsequent PRs:

  • Legacy compat behaviors (for python 3.7)
  • Background / typed function signatures support.
  • Gunicorn/Worker Integration: Defining a custom Gunicorn application or configuration that utilizes uvicorn workers (instead of gthread or sync workers) when an async function is detected. Gunicorn is still the recommended production server for serving ASGI workload (doc).
  • @errorhandler Support: Implementing error handling registration and execution for async functions, similar to the existing Flask-based error handlers.
  • Timeout Handling: Ensuring that function timeouts are correctly enforced within the ASGI/async execution context.
  • Context Propagation: Proper management and propagation of context variables like execution_id and span_id across await boundaries using mechanisms like contextvars.

Partially addresses #192, #194

@taeold taeold changed the title Support async functions feat: Add support for async functions Apr 7, 2025
@Zaffer
Copy link

Zaffer commented Apr 20, 2025

Just a quick question; would it be feasible to move off Flask and instead use FastAPI? Some of the benefits of FastAPI would make updates like this a lot less painful imo.

@taeold
Copy link
Author

taeold commented May 8, 2025

Just a quick question; would it be feasible to move off Flask and instead use FastAPI? Some of the benefits of FastAPI would make updates like this a lot less painful imo.

I don't think we would make a move to replace WSGI-based server like Flask with ASGI-based server like FastAPI or Starlette (which powers FastAPI) immediately.

We'd more likely keep Flask-based serving as default serving path for foreseeable future while giving you control over trying out ASGI-based serving (via environment variable).

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

Successfully merging this pull request may close these issues.

2 participants