1

I'm using server-side event in PHP/jQuery. here is the client side:

var evtSource = new EventSource("testsse.php");
        evtSource.onmessage = function(e) {
           // DO SOMETHING WITH e
        }

Here is the server side file : testsse.php

header("Content-Type: text/event-stream\n\n");
while (1) {
  echo "message";  
  ob_flush();
  flush();
  sleep(1);
}

It works fine, but when the client close its browser or disconnect, the testsse.php continue running. My problem is that we quickly have many running scripts that overload the server. I already read the following questions:

I already read the following questions :

The last one is interesting, but that's finally the server that tell to the client this is the end. In our case, we would like the scripts automatically die when the client is closed. One solution is to fire an event when tab or browser is closed (Detect browser or tab closing). But unfortunately, this solution is known to be unreliable. And in my opinion, this is not a "professional" option.

Is there a way to properly kill the server side script when the client exit ?

Paul R
  • 208,748
  • 37
  • 389
  • 560
Mr Robot
  • 1,037
  • 9
  • 17
  • Possible duplicate of [How can i stop a server sent event script from running when the user closes the page? PHP](https://stackoverflow.com/questions/28850986/how-can-i-stop-a-server-sent-event-script-from-running-when-the-user-closes-the) – Juakali92 Mar 13 '18 at 13:53
  • Yes, as I mentioned, I already read this solution. But I can't access to the apache configuration on the server. – Mr Robot Mar 13 '18 at 14:02
  • 1
    you mentioned this after editing the question. – Juakali92 Mar 13 '18 at 14:06
  • You can use multithreading in PHP, you can use sockets and reliable `socket_select()` function. You don't have to run a single PHP script for each connection. Let one script handle many connections. – Daniel W. Mar 13 '18 at 14:27
  • Is your PHP script running as an Apache module? If not, how is it being started? – Darren Cook Mar 15 '18 at 08:37
  • Is that your exact testsse.php script? If it is, the code is not using the SSE protocol, and that might even cause the behaviour you see. (But you would never have got anything on the client, which would you be a more major problem than the one you describe...) – Darren Cook Mar 15 '18 at 08:45
  • No it's not the exact script, I removed the events for confidentiality reason. But the answer proposed by Emil solved my problem. – Mr Robot Mar 16 '18 at 09:15

1 Answers1

1

The easiest solution is to let the script timeout and using the build-in retry method.

This means that the connection will close periodically, and if the user is still there, will restart the connection from the frontend.

html5rocks.com has a nice tutorial on SSE here.

Some Pseudocode to show what i mean

JavaScript CODE

var evtSource = new EventSource("testsse.php");
evtSource.onmessage = function(e) {
  // DO SOMETHING WITH e
}

PHP CODE

header("Content-Type: text/event-stream\n\n");

//Live for 60 seconds
set_time_limit(60);

//Set retry to ~1/60 second
echo "retry: 16\n\n";
ob_flush();
flush();

//Run your loop
//It will die in 60
while (1) {
  echo "message";  
  ob_flush();
  flush();
  sleep(1);
}
Emil S. Jørgensen
  • 6,216
  • 1
  • 15
  • 28
  • This approach has a serious problem: your SSE script will die after 60 seconds processing, even if the client is still connected. (OK, "serious" might be over-stating it, as the SSE protocol means the browser will detect this and automatically re-connect.) – Darren Cook Mar 15 '18 at 08:39
  • @DarrenCook That is correct, but only really a problem if you are relying on some serverside state, in which case you must find a way to “tell” the SSE thread that the user is still here. A simple solution to this would be to have a separate `heartbeat` method calling periodically from the frontend (AJAX every ~40 seconds should be fine) and have the server save a timestamp in a way accessible to the SSE thread (Database or $_SESSION seems the most obvious choices). You could then test for this in the SSE threads loop and extend the remaining time using `set_time_limit`. – Emil S. Jørgensen Mar 15 '18 at 09:28