I would like to refresh my static web page running on apache when the index changes. I've already tried to use server-side events, where I had a PHP file checking if the index changed and if yes, it sent the event to the webpage. This works exactly how I want, but there is a problem. Because the page is used by a lot of people sometimes (tens or up to a hundred opened tabs), it quickly starts to spam many apache processes. Then, it reaches the limit, and the apache freezes. The question is how to handle this. If a user closes the tab, the process is killed, however, if not, the apache freezes.
The PHP script looks like this (it is checking two things, first, if the file chenged, or second if the status is something. As I said, this works fine, the problem is its lagging the server):
<?php
session_start();
session_write_close();
ignore_user_abort(false);
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
$filename = "index.html";
while(True){
if ( connection_aborted() ){
exit();
}else{
try{
$string = file_get_contents("current_status.json");
$json = json_decode($string, true);
$pom1 = $json["state"];
$t1 = shell_exec("date -r index.html");
sleep(3);
$pom2 = $json["state"];
if($t1 != shell_exec("date -r index.html")) {
sleep(2);
echo "data: file changed \n\n";
} else if($pom2=="ready") {
sleep(2);
echo "data: new shot available \n\n";
} else {
echo "heartbeat";
}
ob_flush();
flush();
}
catch (\Error $e){
echo "data: error, json not available \n\n";
}
}
}
ob_end_flush()
?>
Then, there is a classical javascript function in the index file with event source on the PHP file.
My question is, how can I do this to not make apache crashing? Can I somehow set up SSE to handle it? I know I can allow more processes on apache, but my resources are limited.
Is there any other way how to do this? For example, live.js works as well, but the problem is the sam, a lot of processes when opened multiple times.
Yes, I can see how this would put far more strain on your server than necessary.
What you should do is poll for changes from javascript. You send an asynchronous request for the last time the index file changed from your javascript. You do it once when the page loads and store the time. Then you check again on an interval and compare the result with the first one. If it changed you refresh the page. The PHP script should get the last change date, output it and exit - no continuously running PHP scripts.
Here is what the PHP file should look like:
<?php
header('Content-type: text/plain');
echo filemtime('index.html');
?>
Keep this minimal. The built in filemtime function is more efficient than running shell_exec commands.
Here is an example javascript:
chk_index_change_time(false);
function chk_index_change_time(last){
fetch('http://yourdomain.com/yourpath/get_index_change_time.php')
.then(res => res.text())
.then((index_change_time) => {
if ((false !== last) && (last != index_change_time)){
location.reload();
} else {
setTimeout(chk_index_change_time, 3000, index_change_time);
}
});
}
Feel free to error handling or whatever, but this will work. I used a timeout here instead of interval so that if the server is slow the server response time doesn't come out of the 3 second delay.