Skip to content

[BUG] Support for ASGI startup events #911

Open
@gsaiz

Description

@gsaiz

Investigative information

Please provide the following:
  • Timestamp: 2021-11-10T10:58:00
  • Function App name: (debugging locally)
  • Function name(s) (as appropriate):(debugging locally)
  • Core Tools version: 3.0.3785 Commit hash: db6fe71b2f05d09757179d5618a07bba4b28826f (64-bit)

Repro steps

Provide the steps required to reproduce the problem:
  1. Setup a new Function App, with an HTTP trigger and the following code in func/__init__.py:
import logging

import azure.functions as func
from azure.functions import AsgiMiddleware
from api_fastapi import app

IS_INITED = False


def run_setup(app, loop):
    """Workaround to run Starlette startup events on Azure Function Workers."""
    global IS_INITED
    if not IS_INITED:
        loop.run_until_complete(app.router.startup())
        IS_INITED = True


def main(req: func.HttpRequest, context: func.Context) -> func.HttpResponse:
    asgi_middleware = AsgiMiddleware(app)
    run_setup(app, asgi_middleware._loop)
    return asgi_middleware.handle(req, context)
  1. After the 1st request, you will get the following exception:
[2021-11-10T09:58:11.178Z] Executed 'Functions.api_az_function' (Failed, Id=50cbe047-48bd-42be-9314-0194c2e17ec9, Duration=65ms)
[2021-11-10T09:58:11.181Z] System.Private.CoreLib: Exception while executing function: Functions.api_az_function. System.Private.CoreLib: Result: Failure
Exception: RuntimeError: Task <Task pending name='Task-39' coro=<AsgiResponse.from_app() running at C:\Program Files\Microsoft\Azure Functions Core Tools\workers\python\3.8/WINDOWS/X64\azure\functions\_http_asgi.py:65> cb=[_run_until_complete_cb() at C:\Users\User\AppData\Local\Programs\Python\Python38\lib\asyncio\base_events.py:184]> got Future <Future pending> attached to a different loop

Expected behavior

Provide a description of the expected behavior.
  • The Function should be able to fulfil any number of requests.

Actual behavior

Provide a description of the actual behavior observed.
  • Because the AsgiMiddleware is instantiated for each call, the event loop is not reused and thus we get the exception.

Known workarounds

Provide a description of any known workarounds.
  • Have a global AsgiMiddleware object as shown here:
import logging

import azure.functions as func
from azure.functions import AsgiMiddleware
from api_fastapi import app

IS_INITED = False
ASGI_MIDDLEWARE = AsgiMiddleware(app)


def run_setup(app, loop):
   """Workaround to run Starlette startup events on Azure Function Workers."""
   global IS_INITED
   if not IS_INITED:
       loop.run_until_complete(app.router.startup())
       IS_INITED = True


def main(req: func.HttpRequest, context: func.Context) -> func.HttpResponse:
   run_setup(app, ASGI_MIDDLEWARE._loop)
   return ASGI_MIDDLEWARE.handle(req, context)

Contents of the requirements.txt file:

Provide the requirements.txt file to help us find out module related issues.
azure-functions==1.7.2
fastapi==0.70.0

Metadata

Metadata

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions