SSE with Angular and node.js unable to emit events from multiple modules

Viewed 35

I am trying to set up Server-Sent Events since I have some processes on the node server that can take a long time and I don't want to try and keep a connection open so am trying to get the server to message when a process is done.

I believe I have the Angular side working fine. It is on the node.js side that I am having problems. I have tried many configurations but this is my latest.

sse-controller.js (this is what the Angular app calls)

const express = require("express");
const app = (module.exports = express());
const service = require('./sse-service');

app.get('/api/sse', async (req, res) => {
    await service.createStream(res);
  });

sse-service.js

const Stream = new (require('events')).EventEmitter();

const createStream = async (res) => {
    
    res.writeHead(200, {
        'Content-Type': 'text/event-stream',
        'Cache-Control': 'no-cache',
        Connection: 'keep-alive',
    });

    Stream.on('push' , (event, data) => {
        res.write('event: ' + String(event) + '\n' + 'data: ' + JSON.stringify(data) + '\n\n');
    });

    Stream.emit('push', 'message', 'data');
    
}

const emitStream = async (message, data) => {
    Stream.emit('push', message, data);
}

module.exports = {
    createStream,
    emitStream,
}

Then some module that wants to emit an event

const sse = require("../SSE/sse-service");

const calculateTotals = () => {
    .
    .
    .
    sse.emitStream('completed', 'totals');
}

Right now The Stream.emit in the createStream function is only there to make sure that the eventEmitter works and I do see this on the front end so I know that it is working. When I call the sse.emitStream from some other module that has imported sse-service it does call the emitStream but either the Stream.emit doesn't work or the Stream.on does not catch the event.

When I import the module do I lose the original Stream? Or am I doing something else incorrectly?

Many thanks in advance.

UPDATE:

Well in continuing to research this there were two things that were causing me problems. One is that in the Stream.on the event (not the event name) I was passing was 'messages' but this seems to cause a problem in writing to the response. It must be 'message'. It shows in the response with type: Tried to find documentation that list what events where allowed but didn't really find anything and decided not to pursue it because of the issue I found below.

What seemed to be causing me the main problem is the machine I was running on has 4 cpus and we are using cluster. So I was connecting to one of the threads but when the process was done it calling the Stream.emit on another thread. If I limit the machine to one thread then the process works.

I am not marking this as closed yet since I would be interested if anyone has a simple way to implement sse for clusters but right now I think I am going to look at other solutions to my problem.

UPDATE 2

The reason for the first issue above is actually on the Angular side. I am reading the stream using EventSource and had defined the onmessage and onerror so the only events it would see is a 'message' or 'error'.

0 Answers
Related