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'.