[RESOLU] Exécuter qu'une seule fois un script php

Avatar du membre
Eléphant du PHP | 224 Messages

27 janv. 2021, 17:10

Coucoutte :)

Voilà, sur le site de la radio, j'ai un souci qui se produit de temps en temps, ce n’est pas super grave mais ça me dérange quand même .

Chaque visiteur déclenche toutes les 5 secondes, via une requête Ajax, l'exécution d'une page php qui :
- Récupère les titres joués depuis le dernier "ramassage", sur une base SQL distante (du PC Diffusion, RadioDJ) , et les ajoute à une table "historique".
- Récupère les titres à venir depuis cette même base, et met à jour une table "queuelist".
- Envoie un mail aux auditeurs enregistrés (compte tchat) ayant dans ses titres favoris, un des titres à venir, pour le prévenir qu'il va être joué dans quelques minutes.
- Gère le display et l'affichage des pochettes (en cours et 5 titres récemment joués).

Afin que le PC RadioDJ ne soit pas sursollicité ( x requêtes x le nombre de visiteur x 5 secondes), il y a un petit système en place :
Dans une table du site, le script note la date et heure du dernier ramassage et passe à 1 un paramètre de verrouillage. Lorsque le script st exécuté, il regarde ces 2 paramètres et si le dernier ramassage a plus de 5 secondes, il déverrouille, met à jour la date, reverrouille, et fait un nouveau ramassage.

Ainsi, le PC Radio DJ ne reçoit plus qu'une sollicitation toutes les 5 secondes au lieu de dizaines ou centaines (qui le faisaient freezer car n'a plus de temps pour lui, pour écrire dans sa DB).

Chaque ramassage est loggé dnas un fichier avec date et heure, et IP du déclencheur.

Seulement, de temps en temps, il se trouve que 2 visiteurs (dans les logs, ce sont bien 2 IP différentes pour la même heure de ramassage) déclenchent pile en même temps le script, qui est donc exécuté 2 fois (pas gênant à ce stade pour RadioDJ) ce qui entraîne :
- Ajout en double du titre en cours dans la table "historique"
- Envoie en double du mail de favoris si un mail devait être envoyé (cas statistiquement plus rare ceci dit).

Code : Tout sélectionner

$delta = strtotime($now) - strtotime($last_rdj_data); // si dernier ramasse il y a plus de 5 sec ou si l'histo_lock est verrouillé depuis plus de 10 sec if (($delta >= 5 && $histo_lock == 0) || ($delta >= 10 && $histo_lock == 1)) { $sql = "UPDATE config SET valeur = '1' WHERE critere = 'histo_lock'"; $requete = mysqli_query( $dbwrite, $sql ); // On mets à jour l'heure du dernier essai ramassage sur la DB site $sql = "UPDATE config SET valeur = '$now' WHERE critere = 'last_rdj_data'"; $requete = mysqli_query( $dbwrite, $sql ); $fp = fopen ("test5sec.txt", "a+"); fputs ($fp,"$now Delta : $delta s - Client : $client\n"); fclose ($fp); [...]Ramassage des titres depuis la base RDJ, envoi des mails de favoris[...] } // Fin du ramassage [...]Gestion du display et des pochettes en fonction de ce qui est présent dans les tables de la base SQL du site[...]
Comment serait-il possible d’empêcher la partie ramassage de pouvoir être exécutée 2 (ou +) fois ? Je pensais que verrouiller et mettre à jour la date et heure du dernier ramassage serait suffisamment rapide pour pas qu'un autre exécute le script mais ce n'est pas 100% efficace (faut quand même le faire pour que ça tombe pile en même temps à la milliseconde ou quelques millisecondes près).

Si quelqu'un a une astuce à explorer :)

Merkouin !
Un Couin vaut mieux que Deux tu couineras :D
Retrouvez-moi tous les dimanches soir à 22H pour un mix live au vinyle sur eurodance90.fr :mrgreen:

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 10684 Messages

27 janv. 2021, 19:55

Hello !

En fait c'est un problème informatique récurrent, ton script qui contrôle le statut fait la course avec celui qui l'utilise (ça s'appelle du TOC/TOU pour ceux que ça intéresse :)).

Je ne sais pas quelle est la meilleure solution pour y parer, mais tu jeter un oeil du côté des sémaphores en php : https://www.php.net/manual/fr/book.sem.php (sem_get, sem_aquire, sem_release...)
Ce n'est pas en améliorant la bougie que l'on a inventé l'ampoule...

Avatar du membre
Eléphant du PHP | 224 Messages

28 janv. 2021, 01:47

Plop !

Merci pour ta réponse :)

Bon je sens que ca va encore être un truc qui rend surtout TOC-TOC :(

Et j'avoue que je ne comprends absolument rien à l'utilisation de sémaphores, la doc php est vraiment plus que succincte :(
Et 10 pages de google pour trouver un exemple concret, précis (et surtout compréhensible de comment utiliser ça et dans quel ordre, sans succès :(
Un Couin vaut mieux que Deux tu couineras :D
Retrouvez-moi tous les dimanches soir à 22H pour un mix live au vinyle sur eurodance90.fr :mrgreen:

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 10684 Messages

28 janv. 2021, 13:43

J'ai trouvé ça qui peut éventuellement te permettre d'y voir un peu plus clair, mais c'est effectivement pas super évident comme système
https://stackoverflow.com/questions/399 ... semaphores

Après, ça vaut ce que ça vaut, mais une solution beaucoup plus simple et qui semble pas trop mal marcher (ça reste quand même à tester, je ne l'ai jamais fait), c'est de gérer ton verrou sous la forme d'un dossier sur le serveur.

La fonction mkdir a en effet cet avantage de ne pas pouvoir créer un dossier si celui-ci existe déjà. Cela permet de tester la présence d'un verrou - et à défaut d'en poser un - dans une seule instruction. Si le dossier existe déjà quand mkdir tente de le créer, il ne peut pas l'écraser comme un fichier ou une info en base, il retourne false et c'est terminé.

Ça coute pas grand chose à mettre en oeuvre, je te suggère donc d'essayer et de voir si c'est pertinent ou pas avant de t'arracher les plumes sur les sémaphores ;)
Ce n'est pas en améliorant la bougie que l'on a inventé l'ampoule...

Avatar du membre
Eléphant du PHP | 224 Messages

28 janv. 2021, 16:45

Yop !

En effet je préfère garder mes plumes, on se comprend entre volatiles MDR

Bien vu pour l'astuce du dossier, j'ai mis ça en place donc je verrais ce que ça donne mais je suis confiant :D
Un Couin vaut mieux que Deux tu couineras :D
Retrouvez-moi tous les dimanches soir à 22H pour un mix live au vinyle sur eurodance90.fr :mrgreen:

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 10684 Messages

28 janv. 2021, 19:05

Cool ! Et tiens moi au courant du résultat, je n'ai jamais eu l'occasion de le tester mais l'astuce m'avait semblée pertinente :)
Ce n'est pas en améliorant la bougie que l'on a inventé l'ampoule...

Avatar du membre
Eléphant du PHP | 224 Messages

29 janv. 2021, 00:43

Pouik !

J'ai eu quand même du doublon, alors j'ai changé de méthode :
Je pensais dans un premier temps jouer sur une parité (0 ou 1, calculée par une fonction 'maison') de l'adresse ip visiteur et de ne ramasser que si l'adresse est paire par exemple. Méthode discriminatoire qui aurait réduit les probabilités de doublons mais si en pleine nuit il y a peu de visiteurs et qu'aucun n'a une ip paire, c'est dans l'oignon.
Donc réfléchissage à autre méthode :
J'enregistre dans la DB site, l'ip du dernier ramasseur (en plus de la date et heure du dernier ramassage).
Dans le script à exécuter, je regarde ces deux valeurs.
- Si le delta de temps depuis le dernier ramassage est supérieur à 5 secondes et que l'ip est la même, le script s'exécute.
- Si le visiteur n'est plus sur le site, le ramassage ne se faisant plus, il y a donc une autre condition disant que si le delta est supérieur à 6 secondes avec une ip différente de celle du dernier ramassage, le script s'exécute aussi, et on met à jour l'ip du ramasseur dans la DB.
A suivre lol
Un Couin vaut mieux que Deux tu couineras :D
Retrouvez-moi tous les dimanches soir à 22H pour un mix live au vinyle sur eurodance90.fr :mrgreen:

Avatar du membre
Eléphant du PHP | 224 Messages

03 févr. 2021, 00:36

Pouet!

Plus de doublon depuis le système avec l'IP du dernier ramasseur.

A ploutch' !
Un Couin vaut mieux que Deux tu couineras :D
Retrouvez-moi tous les dimanches soir à 22H pour un mix live au vinyle sur eurodance90.fr :mrgreen: