fanout / django-eventstream

Server-Sent Events for Django
MIT License
638 stars 84 forks source link

send_event doesn't work with pushpin inside container #53

Closed thelotusflower closed 4 years ago

thelotusflower commented 4 years ago

Hi, I have a multi container application setup and I can't configure communication between processes via Pushpin. Container setup is next:

In my django project I installed django-eventstream app and configured everything according your guide. I've set up GRIP_URL to 'http://pushpin:5561'. I've configured routing

from django.conf.urls import url
from channels.routing import URLRouter
from channels.http import AsgiHandler
from channels.auth import AuthMiddlewareStack
import django_eventstream

urlpatterns = [
    url(r'^account/(?P<account_id>\w+)/events/', AuthMiddlewareStack(
        URLRouter(django_eventstream.routing.urlpatterns)
    ), {'format-channels': ['account-{account_id}']}),
    url(r'', AsgiHandler),
]

nginx configured to proxy /events requests to daphne container

location ~* .account/[0-9]/events/$ {
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";

            client_max_body_size 500m;
            proxy_pass http://async_app;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $remote_addr;
            proxy_set_header Host $host;
        }

And in I've also volumed config folder to pushpin container where I put routes file

* async_app_1:80

I've initialized eventsource on front-end:

var es = new ReconnectingEventSource('/account/' + currentUser.accountId + '/events/');

        es.addEventListener('message', function (e) {
            var data = JSON.parse(e.data);
            console.log('Recieved message');
            console.log(data.text);
        }, false); 

        es.onopen = function () {
            console.log('connected');
        };

And in my celery task I call send_event:

def calculate():
    send_event(f'account-{account_id}', 'message', {'text': 'Started calculating'})
    calculate()
    send_event(f'account-{account_id}', 'message', {'text': 'Ended calculating'})

When I load page I see connection being successfuly established and it receives keep-alive message from time to time. But when I trigger my celery task in pushpin container log I see that both times messages were published but no one recieved them

[INFO] 2020-06-08 11:05:03.351 [handler] control: POST /publish/ code=200 10 items=1
[INFO] 2020-06-08 11:05:03.357 [handler] publish channel=events-account-2 receivers=0
[INFO] 2020-06-08 11:05:03.926 [handler] control: POST /publish/ code=200 10 items=1
[INFO] 2020-06-08 11:05:03.926 [handler] publish channel=events-account-2 receivers=0

I've double checked django settings and searched error log for any clue but everything seems to be working fine except that client doesn't get subscribed to message channel for some reason.

jkarneges commented 4 years ago

Hmm, is the client actually connecting to Pushpin?

thelotusflower commented 4 years ago

Could you please explain how can I make sure that a client has connected to Pushpin? I thought it's grip middleware concern to connect clients to Pushpin?

jkarneges commented 4 years ago

Pushpin is a proxy server that must be placed in front of the app, for clients to connect through. Then the app publishes messages to Pushpin. By default, Pushpin listens for client connections on port 7999 and routes them according to the routes file.

I suggest changing the nginx config for the events path to route to pushpin:7999.

thelotusflower commented 4 years ago

Oh I got it all wrong. I thought that Pushping is used as communication layer between processes and grip middleware actually connects clients. Thanks for clarification I got it working so I'm closing this issue.