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

Django 5.1, ASGI, SSE #1501

Open
mamashin opened this issue Dec 1, 2024 · 1 comment
Open

Django 5.1, ASGI, SSE #1501

mamashin opened this issue Dec 1, 2024 · 1 comment

Comments

@mamashin
Copy link

mamashin commented Dec 1, 2024

Hello.

Sorry, I have a question about Django and ASGI. I saw that a similar topic has already been discussed, but I couldn't find a solution for myself.

Unit 1.33
Django 5.1 (support async handling disconnects)
Python 3.11.2
Debian 12

Test Django code:

def sse(request: HttpRequest) -> HttpResponseBase:
    """Small demo of the basic idea of SSE without any redis or other complexity"""
    async def stream(request: HttpRequest) -> AsyncGenerator[str, None]:
        try:
            counter = 0
            while True:
                counter += 1
                if counter != 1:
                    await asyncio.sleep(1.0)
                yield f"data: <div>{counter}</div>\n\n"
        except asyncio.CancelledError:
            logger.debug("SSE Client disconnected")
            raise

    return StreamingHttpResponse(
        streaming_content=stream(request),
        content_type="text/event-stream"
    )

When I run this code under the Uvicorn ASGI server, after closing the connection, I see "SSE Client disconnected" in my dubug log. However, under Unit, nothing happens, with only in unit log:

2024/12/01 11:29:31 [info] 40085#40121 *11 writev(44, 2) failed (32: Broken pipe)

It seems that Django does not detect that the connection is closed, and this is only apparent when I restart Unit. In the logs:

2024/12/01 11:02:55 [warn] 34253#34253 [unit] #516: active request on ctx quit
2024/12/01 11:02:55 [warn] 34253#34253 [unit] #404: active request on ctx free

In a production environment when I use Redis, I see many connections with Unit and Redis in the ESTABLISHED state, even though many connections are already closed. This is a problem for me.

What am I doing wrong 🤔 ?

@mamashin
Copy link
Author

mamashin commented Dec 1, 2024

small addon.

this is my debug ASGI entry point:

import os
from loguru import logger
from django.core.asgi import get_asgi_application

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'conf.settings')
django_application = get_asgi_application()

async def application(scope, receive, send):
    if scope['type'] == 'http':
        # Let Django handle only ASGI HTTP requests
        async def receive_wrapper():
            message = await receive()
            logger.debug(f'ASGI application receive message: {message}')
            await logger.complete()
            return message
        await django_application(scope, receive_wrapper, send)
    else:
        pass

When I connected, I see:

ASGI application receive message: {'type': 'http.request'}

But when I disconnected - log is empty.

As I said, if I run this test under Uvicorn, I see:

ASGI application receive message: {'type': 'http.disconnect'}

Where I lost 'http.disconnect' while working with Unit ?

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