Fel
Fel

Reputation: 4818

Error getting SSE messages, Angular frontend, Node backend

I'm using SSE to send simple messages from a Node backend to an Angular app. So far, it's been working flawlessly, but today I realized that it's not working anymore and I can't find the reason.

This is the relevant code:

NODE

router.get('/stream', function (req, res) {
    [ ... ]

    // Send headers for event-stream connection
    res.writeHead(200, {
        'Content-Type': 'text/event-stream',
        'Cache-Control': 'no-cache',
        'Connection': 'keep-alive'
    });
    res.write('\n');

    [ ... ]
    // NOTE: This line connects to a Redis server
    subscriber.subscribe(channel);

    // In case we encounter an error...print it out to the console
    subscriber.on("error", function (err) {
        logger.debug("Redis Error: " + err);
    });

    // When we receive a message from the Redis connection
    subscriber.on("message", function (channel, message) {
        logger.debug('MESSAGE RECEIVED: ' + message);   // This message is printed in the log file

        [ ... ]
        // Note: 'msgData' is obtained by parsing the received 'message'
        // Send data to the client
        res.write('data: ' + msgData + "\n\n");
    });
}

Angular app

declare var EventSource : any;

getSSEMessages(): Observable<string> {
    let sseUrl = `${ConfigService.settings.appURL}/stream`;    

    return new Observable<string>(obs => {
        const es = new EventSource(sseUrl, { withCredentials: true });  

        // This prints '1' (CONNECTION OPEN)
        console.log('SSE Connection: ', es.readyState);               

        // Note: I've also tried 'es.onerror'
        es.addEventListener("error", (error) => {
            console.log("Error in SSE connection", error);

            return false;
        });

        // Note: I've also tried 'es.onmessage'
        es.addEventListener("message", (evt : any) => {
            // Never gets in here
            console.log('SSE Message', evt.data);

            obs.next(evt.data);
        });

        return () => es.close();
    });
}

This is how I get the messages when I select the option in the interface:

this.getSSEMessages()
  .subscribe(message => {
    // SHOW MESSAGE TO THE USER
});

As I said, everything has been working fine for weeks. Today I saw that I wasn't getting any messages and I've been trying to find out the reason without luck.

Any clues on what can be wrong?

Upvotes: 1

Views: 1660

Answers (1)

Fel
Fel

Reputation: 4818

Finally, I've found a solution:

Perhaps because of updating some Node modules or Node itself, it added some sort of buffer for optimizing the connection traffic. To make the application work again, all I've had to do is add a flush after each message, like this:

[...]
res.write('data: ' + msgData + "\n\n");

// Send the message instantly
res.flush();
[...]

Cheers,

Upvotes: 2

Related Questions