Recherche solution pour éviter le timeout a 30sec.

Eléphant du PHP | 168 Messages

28 nov. 2013, 14:57

Bonjour,

Le topo : Je récupère un fichier XML via simplexml_load_file($url) ou simple_load_string($str) qui boucle ensuite dans un foreach pour supprimer "enregistrements BDD+photos" puis ajouter même chose mais à l'envers pour les données du XML.

Ca marche très bien en local car j'ai accès à mon php.ini pour le time limit mais sur mon mutu (pas le choix) ya un vilain timeout a 30sec me semble il. Ce qui fait que je me prends un Request Timeout en plein milieu de mon foreach.
Les données sont donc incomplètes.


J'ai entendu parlé d'utiliser conjointement fopen/ftell pour ne charger qu'une partie du xml par tranche de 30sec puis via fseek pointer sur le reste à faire après un refresh via header. Mais je n'ai pas réussi à l'appliquer dans mon cas de XML.

J'ai donc pensé à une seconde solution, ne pas attaquer le problème au niveau du xml, mais plutot de mon array $annonces contenant les lignes du XML. Est il possible mémoriser où en est le foreach quand les 30sec arrivent puis refresh et reprendre un foreach à la ligne suivante ? Si oui comment.


Merci

ViPHP
xTG
ViPHP | 7331 Messages

28 nov. 2013, 17:19

J'ai donc pensé à une seconde solution, ne pas attaquer le problème au niveau du xml, mais plutot de mon array $annonces contenant les lignes du XML. Est il possible mémoriser où en est le foreach quand les 30sec arrivent puis refresh et reprendre un foreach à la ligne suivante ? Si oui comment.
Variable de session enregistrant l'index de la boucle de parcours ? :D
Et faire une boucle qui ne fait que X enregistrements et ne pas penser en terme de secondes, tant que ça prend moins de 30secondes c'est bon.

Mammouth du PHP | 571 Messages

28 nov. 2013, 19:10

l'api XMLWriter ou le parseur sax est prévu pour le type de traitement(parsing de gros fichiers xml) que tu souhaites effectuer.

Eléphant du PHP | 168 Messages

28 nov. 2013, 19:14

Merci de vos réponses.

L'endroit où ca coince n'est pas sur le fichier XML en lui même mais le redimensionnement de 4 images à chaque ligne du fichier.

je teste l'histoire de la session/id incrementé.

Eléphant du PHP | 168 Messages

28 nov. 2013, 21:09

J'ai résolu mon problème en croisant finalement une partie avec une variable qui s'incrémente ($i) et en calculant que le script tourne pas + de x secondes, sinon header qui refresh puis une condition qui fait un "continue;" dans mon foreach si l'id est inférieur au précédent refresh.

Bref pas sur ce que ca soit clair, mais voila ca marche :)


Merci

Eléphant du PHP | 168 Messages

29 nov. 2013, 11:55

Finalement fausse joie....

Ca marche parfaitement....mais dans le navigateur.

Le cron de cPanel ne suit pas le
header("Refresh:1;url='http://www....
et j'ai testé avec un
header("location:http://w
Ca le suit bien mais ca me provoque le problème de timeout initial....


Je suis dépité.. Il y a une solution pour que ca soit interprété par cron ?

Merci

ViPHP
xTG
ViPHP | 7331 Messages

29 nov. 2013, 16:23

Il faut que ça soit l'exécution de ta tâche Cron qui fasse office de "refresh" dans ce cas.
En gros à chaque exécution de la tâche cron tu exécuteras une portion du traitement.

Eléphant du PHP | 168 Messages

29 nov. 2013, 16:27

Tu veux dire que je dois avoir plusieurs crons ? Pas sur de comprendre.
Qu'appelle tu que ca soit le cron qui se refresh ?

ViPHP
xTG
ViPHP | 7331 Messages

29 nov. 2013, 17:40

Ton cron exécute toujours le même script, une seule tâche Cron.
Mais le script qui découpe le traitement comme tu le fais maintenant.
Donc à chaque fois que la tâche Cron se lancera tu reprendras le traitement là où il s'était arrêté.

Par contre le système de session ne sera peut être pas top, faut voir pour remplacer cela avec un fichier. :)

Mammouth du PHP | 2278 Messages

29 nov. 2013, 17:43

Je suis peut-être Hors sujet:
le fichier est entièrement lu AVANT le time out, et il est dans un fichier quelque part dans l'arborescence du serveur web quand tu le traites?
Il me semble qu'en lisant le fichier ligne par ligne dans un truc de ce genre:
longueur deja chargee = 0
temps passe = 0
while (temps_ecoule < timeout)
$ligne = fgets(handle)
long = longeur(ligne)
longueur deja chargee+= long
traitement
calculer temps passé
wend
enregistrer en session longueur deja chargee
Vanitas vanitatum et omnia vanitas
Mes derniers livres :
Sauvez les Mots chez BoD,
Tous les chemins mènent à ROM chez BoD

Eléphant du PHP | 168 Messages

29 nov. 2013, 17:51

@xTG : Ok donc mettre par exemple un cron toute les 5 minutes et si le fichier n'est pas fini ca reprend ( et du coup faire que 30sec ou x enregistrements par session de cron. L'approche mérite d'être testé et voir comment faire aussi pour pas que ca cron tout la journée pour rien ensuite.

@sirakawa : Ce n'est pas le fichier qui est long dans mon cas, c'est que pour chaque ligne du XML qui est devenu un array, ben je récupère 4 photos distances, et dont chacune est décliné en 3 formats différents (original, miniature de liste, et apercu de slide). Et c'est donc ce travail qui me prend du temps et génère un timeout.

Mammouth du PHP | 504 Messages

30 nov. 2013, 19:56

Hello,
set_time_limit(2000);


la doc: http://php.net/manual/fr/function.set-time-limit.php Le temps est en seconde.

à inclure au tout début de ton fichier php qui trairte ton cron. Cela va augmenter le temps d'éxecution de ton script seulement sur ce fichier. le reste restera dependant de ton php.ini.

Je le fais chez moi, ça marche trés bien. Je précise que c'est un dédié mais je ne vois pas pourquoi ça ne archerai pas sur un mutu.

Eléphant du PHP | 168 Messages

30 nov. 2013, 19:59

Le serveur est un mutualisé et a le safe mode activé, cette commande est donc ignorée :)