Server Sent Events : ne retourner aucune donnée + $GLOBALS
Bonjour,
Merci à vous de vous pencher sur mes problèmes :-)
Problèmes
- mon client JS reçoit des notifications du serveur SSE même si ce dernier n'a rien à envoyer
- pourquoi les timestamp fonctionnent en $_SESSION et pas en $GLOBALS ?
Client side (JS)
Le client JS s'abonne à un serveur SSE et traite ses messages :
Code:
1 2 3 4 5 6 7 8 9 10
| function serverPushOk()
{ // Le client JS s'abonne au serveur SSE en donnant son ID et le code de son PROFILE
_sseSource=new EventSource("sseServer.php?cmd=9&userId="+_$store.sysGet("userId")+"&userProfile="+_$store.sysGet("userProfile"));
// Traitement d'un message SSE en provenance du server
_sseSource.onmessage=function(event)
{ // Ici, on reçoit la liste des tables à mettre à jour
// Elles le seront à la prochaine connexion dont on profitera pour envoyer les mises à jour à faire dans les tables du serveur
...code...
};
} |
Server side (PHP)
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| <?php
// 1. on interroge la base de données pour avoir le timestamp de chaque table
...code...
session_start();
// 2. si $_SESSION de la table n'existe pas ou que le timestamp des bases de données est plus récent que celui de $_SESSION de la table, on ajoute le nom de la table à $update
...code...
header("Access-Control-Allow-Origin: *");
header("Content-Type: text/event-stream");
header('Cache-Control: no-cache');
if($update!='')
{ echo 'data: '.$update."\n\n";
}
session_write_close();
sleep(20);
?> |
Problème 1
Le client JS reçoit un event toutes les 20 secondes = sleep(20) même s'il n'y a aucune mise à jour de tables. Il ne traite pas puisque qu'il n'y a pas de event.message mais cela consomme-t-il de la data pour le client ?
Si je déplace les header() dans le bloc if($update!=''), le script ne fonctionne plus
Problème 2
Le client JS fait périodiquement des appels Ajax pour mettre à jour des tables sur le serveur. Mon idée était de mettre le dernier timestamp d'une table modifiée en $GLOBALS pour éviter une requête base de données pour récupérer les timestamp.
C'est manifestement une idée à la c*n puisque cela ne fonctionne pas (mais c'est ok en $_SESSION). Je suis sur un serveur mutualisé, il se peut que cela apporte un élément de réponse.
Merci de votre attention et de vos éventuels retours.
2 pièce(s) jointe(s)
Problème 2 : informations complémentaires
Merci de cette cette réponse.
Voici l'architecture de l'application qui va mieux (je l'espère) expliquer le contexte :
Pièce jointe 622337
Mon idée (pourrie puisque ne fonctionnant pas) était que, puisque qu'un $_SESSION (sous ensemble de $GLOBALS) défini dans script A était visible dans script B, un $GLOBALS["xxx"] défini dans script A serait visible dans script B.
Donc mon idée était :
- script A mémorise dans un $GLOBALS le timestamp des tables => sera donc visible par toutes les sessions de script B
- script B compare le timestamp $GLOBALS des tables aux timestamp $_SESSION pour décider s'il faut faire une mise à jour
1 pièce(s) jointe(s)
Problème 1 : informations complémentaires
Voisi le détail du script A de l'architecture :
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
| <?php
error_reporting(E_ALL);
ini_set("display_errors", "On");
define('_VERSION','1.0.5');
define('_PS_ADMIN_DIR','../../');
include(_PS_ADMIN_DIR.'config/config.inc.php');
{ session_start();
// *partA*
// On récupère les timestamp des tables de la base de données
// Les timestamp sont stockés dans une table car (voir mon problème 2 :-)
$req='SELECT * FROM `xxx.data` WHERE `xxx.data`.`varId`=1;';
$res=Db::getInstance()->executeS($req);
$stamps=[];
if ($res[0]['varData']!='')
{ $tmp=explode('|',$res[0]['varData']);
for($i=0;$i<count($tmp);$i++)
{ $data=explode('=',$tmp[$i]);
$stamps[$data[0]]=$data[1];
}
}
$update='';
// *partB*
// Si les timestamp de $_SESSION sont inexistant ou inférieurs aux timestamp de la base de donnée, on signifie une demande de mise à jour
foreach($stamps as $key=>$value)
{ if(!isset($_SESSION[$key]) || (($value-$_SESSION[$key])>20))
{ $update.=$key.'-'.$_SESSION[$key].'-'.$value;
$_SESSION[$key]=$value;
$update.='-'.$_SESSION[$key].'|';
}
}
$update=substr($update,0,-1);
session_start();
// *partC*
// headers
header("Access-Control-Allow-Origin: *");
header("Content-Type: text/event-stream");
header('Cache-Control: no-cache');
if($update!='')
{ // *partD*
// On envoie un message SSE au Process 1 du client pour signifier une mise à jour nécessaire
echo 'data: '._VERSION.':'.$update."\n\n";
}
else
{
// *partE*
}
session_write_close();
sleep(20);
}
?> |
*partA, *partB* et *partD* fonctionnent bien.
Le problème, c'est quand il n'y a aucune modif à envoyer (*partE*) : la console Firefox (client side) me rapporte une activité toutes les 20 secondes (sleep(20) en fin de script A) :
Pièce jointe 622340
Comment éviter que script A envoie un message à Process 1 quand il n'y a aucune modification ? (cas *partE*) ?
Déplacer les headers *partC* dans *partD* provoque une erreur dans Process 1 "Firefox ne peut établir de connexion avec le serveur à l’adresse xxx/sseServer.php" quand il n'y a aucune modification à envoyer.