Question

I have an area in my page where messages go when a database has changed. Now, some days the database will change so much that a new message is displayed every 10 minutes; other days it will change only a few times. The issue I am having is that the EventSource seems to time out after 1hr 22 minutes, and no longer will the browser receive notifications.

I am wondering if there is a way to keep EventSources persistent (i.e., for as long as the browser is displaying the page, the EventSource is alive). According to what I have found in my Google searches, EventSources should remain alive until the tab/window is closed. Unfortunately, there seems to be so very little that I find in my Google searches, and for me this doesn't seem to be the case.

Was it helpful?

Solution

You don't say where the socket closure is happening (on the browser, socket on client machine, socket on server-side, etc.) but it doesn't really matter as the fix is the same for all of them: send keep-alive messages.

The server should send a keep-alive message. Either every, say, 15 seconds; or only after 15 seconds of inactivity. (Whichever is easier to code, server-side, for you.) It can be as simple as an SSE comment: ":\n\n" (lines starting with colons are ignored). I prefer to send actual data, because:

  • You get to see a message, allowing client-side keep-alive checking (see below)
  • There is bound to be something useful you want to send, like a timestamp (for a check that client/server clocks are in sync), or metrics, etc.

On the client-side, run a timer with setTimeout() set to 20 seconds. Each time you receive any data from the server (whether genuine data, or your keep-alive), kill the timer, and start it again. Therefore the only time the time-out function will get called is if your server went more than 20 seconds without sending you anything. When that happens, kill the connection and reconnect.

The above is assuming the problem is at the socket-level. The problem might instead be the browser is crashing: perhaps it has run out of memory. The fix I'd do in that case is a once/hour timer (setTimeout() in JavaScript), to manually close and re-open the EventSource connection. Or clear out some memory buffers you might be using. A bit of profiling with FireBug or Chrome tools will tell you if you have a memory problem.

Plug: Over half of the "Making our App production quality" chapter in my coming-soon SSE book is about keep-alive and using LastId on the reconnect. Please buy when it comes out :-)

OTHER TIPS

I had the same problem with Chrome reporting "net::ERR_SPDY_PROTOCOL_ERROR 200" every two minutes.

Sending SSE comments every minutes solved the problem for me. See example Nodejs / Express code below.

exports.addWebServices = function(app) {
  app.get('/ws/clientEvent', function(req, res) {
    res.writeHead(200, {
      'Content-Type': 'text/event-stream',
      'Cache-Control': 'no-cache',
      'Connection': 'keep-alive'
    })

    /* Event handlers for SSE here */

    let keepAliveMS = 60 * 1000;

    function keepAlive() {
      // SSE comment for keep alive. Chrome times out after two minutes.
      res.write(':\n\n');
      setTimeout(keepAlive, keepAliveMS);
    } 

    setTimeout(keepAlive, keepAliveMS);
  }

}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top