Comment s'assurer qu'un seul wp_cron () s'exécute à la fois?


9

J'ai environ 20 wp_cron()fonctions telles que le code suivant. Presque tous les crons fonctionnent toutes les heures; quelques-uns sont quotidiens.

if ( ! wp_next_scheduled( 'my_task_hook' ) ) {
  wp_schedule_event( time(), 'hourly', 'my_task_hook' );
}

add_action( 'my_task_hook', 'my_task_function' );

function my_task_function() {
  //Complex Code
}

Pour augmenter les performances du serveur, et pour ne pas continuer à recevoir des messages de limite de serveur des sociétés d'hébergement, je veux m'assurer qu'un seul cron s'exécute à un moment donné ... Est-ce possible?


La réponse actuellement acceptée est excellente, mais j'ai la question suivante, c'est pourquoi je commence une prime pour cette question.

Veuillez d'abord lire la réponse acceptée.

Supposons que Cron 1 fonctionne, mon code de cron2 ne fonctionnera pas parce que nous sommes encore dans les 5 minutes ou le premier cron fonctionne toujours, mais à cause de la wp_schedule_event( time(), 'hourly', 'my_task_hook' );course pour cron2, je pense que WordPress considère que cron2 fonctionne ..... Donc, fondamentalement, le code du code cron2 n'a jamais fonctionné ..... Ou j'ai mal compris quelque chose?


Non, vous comprenez bien. Je mettrai à jour ma réponse avec quelques solutions à votre problème ...
Krzysiek Dróżdż

Réponses:


10

Oui c'est possible...

Et pour être honnête, il est souvent très important de le faire ... WP Scheduler a parfois tendance à causer des problèmes, lorsque les tâches cron sont longues ...

Alors, comment résoudre ce problème?

J'utilise l' API Transients pour implémenter des sémaphores ...

Voici le code:

if ( ! wp_next_scheduled( 'my_task_hook' ) ) {
  wp_schedule_event( time(), 'hourly', 'my_task_hook' );
}

add_action( 'my_task_hook', 'my_task_function' );

function my_task_function() {
  // if some other my_task is already running, stop
  if ( get_transient( 'my_task_function_semaphore' ) ) return;

  // set semaphore for 5 minutes
  set_transient( 'my_task_function_semaphore', true, 5*60 );

  // DO YOUR STUFF

  delete_transient( 'my_task_function_semaphore' );
}

Pourquoi dois-je utiliser des transitoires dans ce cas? Parce que:

  • Ils font partie de WP.
  • Ils sont faciles à utiliser et efficaces.
  • Ils ne provoqueront pas de blocages. Disons que ma tâche cron peut être tuée (une erreur peut se produire, ou elle s'exécute trop longtemps et est tuée, etc.). Dans ce cas, il ne supprimera pas le sémaphore, donc toutes les tâches futures ne fonctionneront pas. L'utilisation de transitoires résout ce problème, car après un certain temps, les transitoires seront supprimés.

Et s'il y a beaucoup d'actions différentes à faire?

Supposons donc qu'il existe de nombreuses tâches cron différentes, qui ne devraient jamais s'exécuter en même temps, mais nous voulons toujours qu'elles s'exécutent toutes ...

Si nous utilisons la solution avec un sémaphore et n'utilisons qu'un seul sémaphore pour toutes ces tâches, alors certaines d'entre elles risquent de ne jamais s'exécuter. Que faire alors?

Dans ce cas, vous devez changer votre façon de penser. Vous n'avez pas de tâches indépendantes, mais une file d'attente de tâches à faire. Vous devez donc l'implémenter de cette manière.

Donc:

  1. Vous ajoutez une sorte de file d'attente (vous pouvez utiliser un tableau et le stocker en option, ou ajouter une table DB personnalisée).
  2. Vous utilisez votre événement horaire WP actuel pour ajouter des tâches à la file d'attente.
  3. Vous ajoutez des secondes tâches cron WP qui s'exécutent beaucoup plus souvent et qui "mangent" les tâches de la file d'attente une par une. Cette tâche "mangeur" ​​doit utiliser un sémaphore pour garantir qu'une seule tâche s'exécute à la fois.

Merci, mais je suis désolé, je n'ai jamais utilisé de transitoire auparavant ... Mais je suis en train de comprendre le code. Pourquoi avez-vous défini 5 minutes pour les transitoires parce que vous supprimez les transitoires à l'aide de delete_transient(). Donc, le temps compte? Je veux dire à chaque fois que vous le mettez set_transient, il est supprimé juste après que mon travail soit terminé ... Alors pourquoi il y a un temps?
Je suis la personne la plus stupide du

Parce que certaines erreurs peuvent se produire. Jetez un œil au dernier point.
Krzysiek Dróżdż

Merci, super ... Juste une question. Si je comprends bien, si j'utilise my_task_function_semaphorecomme nom pour transitoire, je dois utiliser tous les autres crons au même nom?
Je suis la personne la plus stupide du

@IamtheMostStupidPerson cela dépend de ce que vous voulez réaliser ... Si une seule tâche doit fonctionner à un moment donné, alors oui - toutes les tâches doivent utiliser le même nom transitoire que le sémaphore
Krzysiek Dróżdż

1
J'ai fait des choses similaires avec des outils Job Queue comme Gearman. Cette implémentation peut aider: github.com/10up/WP-Minions
Fayaz
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.