django / channels

Developer-friendly asynchrony for Django
https://channels.readthedocs.io
BSD 3-Clause "New" or "Revised" License
6.02k stars 793 forks source link

lifespan support #2018

Open avlubimov opened 1 year ago

avlubimov commented 1 year ago

Error:

[info] 0#929131 [unit] ASGI Lifespan processing exception
Traceback (most recent call last):
  File "/usr/local/lib/python3.11/site-packages/django/core/handlers/asgi.py", line 150, in __call__
    raise ValueError(
ValueError: Django can only handle ASGI/HTTP connections, not lifespan.

Minimal lifespan support for nginx unit application server + django asgi + channels

lifespan.py

from logging import getLogger

logger = getLogger(__name__)

async def LifeSpanHandler(scope, receive, send):
    if scope['type'] == 'lifespan':
        while True:
            message = await receive()
            if message['type'] == 'lifespan.startup':
                await send({'type': 'lifespan.startup.complete'})
            elif message['type'] == 'lifespan.shutdown':
                await send({'type': 'lifespan.shutdown.complete'})
                return
    else:
        logger.error(f"Lifespan handler error, wrong scope: {scope}")

asgi.py

from lifespan import LifeSpanHandler

django_asgi_app = get_asgi_application()

application = ProtocolTypeRouter(
    {
        "http": django_asgi_app,
        "websocket": AllowedHostsOriginValidator(AuthMiddlewareStack(URLRouter(urlpatterns))),
        "lifespan": LifeSpanHandler,
    }
)
carltongibson commented 1 year ago

Hi @avlubimov.

So there's a middleware example in #1216.

Would you fancy adding some docs for this? It's a question that comes up periodically so having a good example/discussion to point people to would be helpful