Passer au contenu
DedicatedPHP Contact

Comment concevoir les délais et l’annulation des processus PHP longs

Définissez des délais par étape, propagez une échéance aux dépendances et consignez les annulations afin que les processus PHP longs se terminent avec un état compréhensible.

Schéma technique d’un processus PHP avec une échéance globale, des limites par étape et un parcours d’annulation

Une importation qui prend des heures, un rapport qui interroge plusieurs sources ou une tâche qui coordonne des intégrations peut continuer à consommer des ressources longtemps après avoir cessé d’être utile. Sans limites explicites, il est également difficile de savoir si elle est en cours, bloquée ou incomplète. Concevoir des délais pour les processus PHP de longue durée exige de définir combien de temps chaque étape peut durer, comment arrêter le travail et quel état conserver si l’exécution est interrompue.

L’objectif n’est pas d’imposer un seul nombre à l’ensemble du processus. Il s’agit d’établir un budget cohérent de bout en bout, de le transmettre aux opérations dépendantes et de faire en sorte que l’état final reflète ce qui s’est passé. Un timeout, une annulation demandée et un arrêt forcé sont des situations distinctes et doivent être traités comme telles.

Pourquoi une limite explicite est nécessaire

Pourquoi une limite explicite est nécessaire — guía visual de DedicatedPHP

Un processus sans échéance peut retenir indéfiniment de la mémoire, des connexions et de la capacité d’exécution. Il peut aussi laisser une tâche marquée comme active alors qu’elle ne progresse plus. Dans un environnement avec des workers, le problème s’amplifie : une exécution bloquée occupe un worker et peut retarder les tâches suivantes.

Les limites de PHP ou du serveur ne remplacent pas une politique applicative. Par exemple, max_execution_time peut limiter l’exécution d’un script, mais ne représente pas nécessairement le temps d’attente total accepté par le métier. En outre, les limites du serveur web, de PHP-FPM, du gestionnaire de files d’attente, du client HTTP et de la base de données peuvent agir indépendamment. Si elles diffèrent, une couche peut terminer le travail sans qu’une autre ait eu le temps d’enregistrer l’état correspondant.

Commencez par déterminer où le processus s’exécute et quels composants peuvent l’arrêter. Une tâche en ligne de commande, un worker de file d’attente et une requête web ont des mécanismes et des conséquences différents. La limite applicative doit coexister avec ces contrôles externes, et non dépendre de l’un d’eux pour gérer seul l’arrêt.

Distinguez timeout, échéance et annulation

  • Timeout d’une opération : durée maximale pendant laquelle un appel donné peut attendre, par exemple une requête ou un appel HTTP.
  • Échéance globale : instant limite pour l’ensemble du processus. Les étapes se partagent le temps restant, au lieu de recevoir chacune la durée totale.
  • Annulation demandée : décision explicite d’arrêter le travail, par exemple parce qu’un utilisateur a annulé la tâche ou que le système l’a retirée d’une file d’attente.

Un timeout indique qu’une opération ne s’est pas terminée dans le budget qui lui était alloué. Cela n’implique pas à lui seul que l’ensemble du processus doit s’arrêter : cela dépend de l’étape et des règles du produit. L’annulation, en revanche, est un signal de contrôle que le processus doit vérifier et traiter lorsqu’il peut le faire en toute sécurité. Ni l’une ni l’autre ne garantit qu’un système d’exploitation ou un superviseur arrêtera une exécution à un point précis ; un arrêt forcé peut survenir entre deux vérifications.

Représentez l’échéance comme un instant absolu ou comme une durée restante calculée à partir d’une horloge monotone. Avant de démarrer une étape, vérifiez qu’il reste du temps. Cela évite qu’une séquence d’opérations avec des timeouts individuels dépasse de beaucoup l’échéance globale. En PHP, encapsulez le calcul et la vérification de l’annulation dans un objet ou un service partagé, au lieu de dupliquer des comparaisons dispersées.

Répartissez le budget entre les étapes et les dépendances

Décomposez le processus en étapes observables : lecture, transformation, écriture et coordination externe, par exemple. Définissez le temps que chacune peut consommer sans dépasser l’échéance globale. Il n’est pas nécessaire que tous les délais soient identiques : une étape dont le travail local est borné peut nécessiter une limite différente de celle d’un appel à un service distant.

Lors de l’appel à une dépendance, utilisez la plus petite valeur entre son timeout opérationnel et le temps restant du processus. Configurez séparément les limites de connexion et de lecture lorsque la bibliothèque le permet. Une connexion rapide n’empêche pas la réponse de tarder, et un timeout de lecture n’inclut pas nécessairement tout le temps écoulé auparavant. Appliquez le même principe aux requêtes SQL, aux opérations de stockage et aux processus secondaires, en utilisant les contrôles proposés par chaque client.

Si une opération ne prend pas en charge l’annulation, ne la présentez pas comme immédiatement interruptible. Vous pouvez limiter la durée d’attente, l’isoler dans une unité de travail distincte ou concevoir le flux de façon à vérifier l’annulation avant et après. Pour les sous-processus, conservez l’identifiant nécessaire pour demander leur arrêt et vérifiez que le processus s’est terminé ; envoyer un signal ne confirme pas qu’il s’est arrêté.

Arrêtez le travail et laissez un état compréhensible

Lorsque l’échéance est atteinte ou qu’une annulation arrive, évitez de démarrer de nouvelles étapes. Aux points sûrs, effectuez les actions locales indispensables pour enregistrer le résultat et libérez les ressources contrôlables, comme les curseurs ou les fichiers temporaires. Le bloc de nettoyage ne doit pas tenter de terminer le travail en attente : sa durée doit également être limitée et il ne doit pas masquer la cause de l’arrêt.

Enregistrez l’état de la tâche dans un emplacement durable, associé à un identifiant stable. Au minimum, consignez des états distincts, par exemple running, completed, cancelled et timed_out, ainsi que l’étape en cours et les horodatages pertinents. Ajoutez un motif compréhensible par les opérateurs, sans enregistrer de données sensibles inutiles. Mettez à jour l’état de manière atomique lorsque c’est possible et tenez compte du fait que le processus peut mourir avant la fin de cette mise à jour.

Le résultat présenté à la personne ayant lancé la tâche doit distinguer « annulée » de « délai dépassé ». Si l’état ne peut pas encore être confirmé après un arrêt brutal, affichez-le comme inconnu ou en attente de vérification, et non comme terminé. Les métriques et les journaux structurés peuvent inclure la durée, l’étape et le type d’arrêt ; évitez d’y consigner des secrets, du contenu privé ou des traces non protégées par un contrôle d’accès.

Déterminez si les effets partiels peuvent être repris

Une interruption peut survenir après l’écriture de données et avant l’enregistrement de la fin de l’étape. Décider si le processus peut reprendre ne consiste donc pas seulement à enregistrer le numéro de l’étape : il faut comprendre quels effets ont pu se produire. Pour les opérations locales, une transaction peut regrouper des modifications liées si sa durée et le moteur le permettent. Ne laissez pas une transaction ouverte pendant un long appel externe.

Pour le traitement par lots, enregistrez les unités terminées avec une clé stable et définissez à quel moment une unité est réellement confirmée. Si une écriture est répétée au redémarrage, la conception doit empêcher les doublons ou reconnaître que l’effet existe déjà. Une intégration externe qui ne prend pas en charge l’annulation peut avoir accepté une requête même si le client a cessé d’attendre ; l’état doit refléter cette incertitude, et ne pas supposer qu’aucun effet ne s’est produit.

S’il n’est pas sûr de continuer à partir du dernier point enregistré, marquez la tâche pour examen ou pour une procédure de récupération spécifique. Une reprise automatique à partir d’un marqueur imprécis peut produire un résultat incorrect. Documentez les étapes qui peuvent être répétées, celles qui nécessitent une vérification et les conditions permettant de déclarer le processus terminé.

Testez les limites et les interruptions

Les tests doivent vérifier aussi bien l’arrêt que l’état final, et pas seulement le déclenchement d’une exception. Utilisez des dépendances contrôlables pour simuler un appel lent, une requête qui dépasse son délai et une réponse qui arrive juste à la limite. Vérifiez que la durée d’une étape ne permet pas d’ignorer l’échéance globale.

Testez une annulation entre les étapes et pendant une opération qui ne peut être arrêtée qu’à son retour. Simulez également un arrêt brutal à des points pertinents : après un effet externe, avant l’enregistrement de l’état et pendant le nettoyage. Après le redémarrage du worker, vérifiez que l’état est compréhensible et que la politique de reprise ne duplique ni n’omet de travail. Ces tests doivent utiliser des données isolées et ne pas dépendre de véritables services externes.

Liste de contrôle pour un processus existant

Liste de contrôle pour un processus existant — guía visual de DedicatedPHP
  • Identifiez les limites de PHP, du serveur, du worker et de chaque client utilisé.
  • Définissez une échéance globale et des budgets par étape qui, ensemble, ne la dépassent pas.
  • Propagez le temps restant à HTTP, à la base de données et aux autres processus lorsque c’est possible.
  • Vérifiez l’annulation aux points sûrs et évitez de démarrer de nouveaux travaux après l’avoir reçue.
  • Enregistrez des états distincts, l’étape en cours et la cause de la fin.
  • Décrivez les effets partiels qui peuvent subsister et les conditions permettant une reprise.
  • Testez les délais, les annulations, les arrêts brutaux et l’état observé après le redémarrage.

Une conception solide ne promet pas que chaque opération pourra être arrêtée instantanément. Elle rend explicite le temps disponible, limite l’attente pour chaque dépendance et conserve suffisamment d’informations pour interpréter une interruption. Cette combinaison permet à un processus long de cesser d’être une exécution opaque et de devenir une unité exploitable et vérifiable.

Vous souhaitez appliquer ces idées à votre projet ?Parlons de votre plateforme PHP.
Afficher les services associés