[BUG] Support for ASGI startup events
See original GitHub issueInvestigative 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:
- 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)
- 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
Issue Analytics
- State:
- Created 2 years ago
- Reactions:1
- Comments:6
Top Results From Across the Web
asgi-lifespan - PyPI
asgi -lifespan provides a LifespanManager to programmatically send ASGI lifespan events into an ASGI app. This can be used to programmatically startup/shutdown ...
Read more >falcon.asgi.app — Falcon 3.1.1 documentation
The interface provides support for handling both ASGI worker lifespan events and per-request events. However, because lifespan events are an optional part ...
Read more >tiangolo/fastapi - Gitter
on_event("startup") , it is reported as INFO: ASGI 'lifespan' protocol appears unsupported. with no more information. Is that a FastAPI bug or a...
Read more >Django Channels, ASGI, and Heroku | by Matt Basta - Medium
The first thing to do was get the service up and running. ... Daphne is a HTTP/websocket protocol server for ASGI, maintained by...
Read more >Release Notes - Starlette
Add WebSocketException and support for WebSocket exception handlers #1263. Add middleware parameter to ... Add reason to WebSocket close ASGI event #1417.
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found

I’ve run across a different issue with the AsgiMiddleware and arrived at basically the same solution as posted above. I noticed that simple async functions do not behave as I would expect an async application should. For example, I tested the following:
If you hit this endpoint above with a few concurrent requests, you’ll notice that they execute serially instead of concurrently (I assume because the AsgiMiddleware blocks with a call to
run_until_completehere). E.g., if I hit this endpoint twice in rapid succession, the second request will take ~10 seconds to complete instead of ~5 seconds.Using a plain azure function without the middleware works as expected (e.g., the above scenario completes in ~5 seconds with two concurrent requests):
As mentioned, the posted solution resolves this, but I’m concerned about the implications of this as mentioned above. It would be great to see a robust solution for this in the near future if possible.
@rbudnar This blocking problem is fixed now here https://github.com/Azure/azure-functions-python-library/pull/143 which also removes the need for
nest_asyncio. But it doesn’t solve this initial issue here.