0

I have a django asgi app that is served by daphne. I am trying to add Server Sent events to stream data from server to client.

My asgi.py:

"""
ASGI config for app project.

It exposes the ASGI callable as a module-level variable named ``application``.

For more information on this file, see
https://docs.djangoproject.com/en/4.1/howto/deployment/asgi/
"""

import os

from django.core.asgi import get_asgi_application

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'app.settings')

application = get_asgi_application()

My django view is below:

import uuid
from django.http import StreamingHttpResponse

from rest_framework.views import APIView

from .sse_helper import register_connection
import logging


log = logging.getLogger("sse_handler")


class MySseView(APIView):
    # authentication_classes = [SessionAuthentication]
    # permission_classes = [IsAuthenticated]


    def get(self, request):
        log.info("Recived get request")
        response = StreamingHttpResponse(content_type="text/event-stream")
        # Set headers to enable SSE support
        response["Cache-Control"] = "no-cache"
        response["Connection"] = "keep-alive"

        # Generate a unique ID for this connection
        connection_id = str(uuid.uuid4())
        business_id = "foo"
    

        # Register the connection in the dictionary
        register_connection(connection_id, str(business_id), response)

        return response

The registered connections are processed by a background thread like this:

sse_connections = {}


def register_connection(connection_id, business_id, response):
   log.info("Registering sse connection %s for business %s" % (connection_id, business_id))
   sse_connections[connection_id + '#' + business_id] = response


def handle_events():
  while True:
    # Iterate over the dictionary of connections
    log.info("Running handle_events on %d items" % len(sse_connections))
    for connection_id, response in sse_connections.items():
        # Send an SSE event to the client
        event = 'message'
        data = f'Hello from background thread! ({time.time()})'
        message = f'event: {event}\ndata: {data}\n\n'
        response.write(message)
        log.info("wrote message")

       # Sleep for a while before sending the next event
       time.sleep(1)


def start():
  log.info("Starting bg thread for sse")
  # Start a background thread to send SSE events
  thread = threading.Thread(target=handle_events)
  thread.daemon = True
  thread.start()

I am running this using daphne server. However i see that daphne is closing the connection after sending response. Is it because of my view being sync?

Below is daphne response:

INFO 2023-03-21 04:26:35,077 views 9642 140491307861568 Recived get request
INFO 2023-03-21 04:26:35,077 sse_helper 9642 140491307861568 Registering sse connection df664db3-12cb-499f-a930-e0b51175058b for business foo
DEBUG 2023-03-21 04:26:35,083 http_protocol 9642 140491467215296 HTTP 200 response started for ['127.0.0.1', 48020]
DEBUG 2023-03-21 04:26:35,083 http_protocol 9642 140491467215296 HTTP close for ['127.0.0.1', 48020]
INFO 2023-03-21 04:26:35,084 _observer 9642 140491467215296 "127.0.0.1" - - [21/Mar/2023:04:26:34 +0000] "GET /events/ HTTP/1.1" 200 - "https://localhost:8001/events" "PostmanRuntime/7.31.1"
DEBUG 2023-03-21 04:26:35,084 http_protocol 9642 140491467215296 HTTP response complete for ['127.0.0.1', 48020]
127.0.0.1:48020 - - [21/Mar/2023:04:26:35] "GET /events/" 200 -
Saurav Prakash
  • 1,880
  • 1
  • 13
  • 24

0 Answers0