Come assicurarsi che venga eseguito solo un wp_cron () alla volta?


9

Ho circa 20 wp_cron()funzioni come il seguente codice. Quasi tutti i croni corrono ogni ora; alcuni sono tutti i giorni.

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
}

Per aumentare le prestazioni del server e non continuare a ricevere messaggi di limite del server dalle società di hosting, voglio assicurarmi che venga eseguito solo un cron alla volta ... È possibile?


L'attuale risposta accettata è ottima, ma ho la seguente domanda, ecco perché inizio una taglia per questa domanda.

Per prima cosa leggi la risposta accettata.

Supponiamo che Cron 1 funzioni, Il mio codice di cron2 non funzionerà perché siamo ancora dentro i 5 minuti o il primo cron è ancora in esecuzione, ma a causa di wp_schedule_event( time(), 'hourly', 'my_task_hook' );cron2 penso che WordPress consideri cron2 funzionanti ..... Quindi sostanzialmente codice di codice cron2 mai eseguito ..... O ho frainteso qualcosa?


No, lo capisci correttamente. Aggiornerò la mia risposta con alcune soluzioni per il tuo problema ...
Krzysiek Dróżdż

Risposte:


10

Sì, è possibile...

E ad essere onesti, spesso è molto importante farlo ... WP Scheduler a volte tende a causare problemi, quando le attività cron sono lunghe ...

Quindi, come risolvo questo problema?

Uso Transients API per implementare i semafori ...

Ecco il codice:

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' );
}

Perché utilizzo i transitori in questo caso? Perché:

  • Fanno parte del WP.
  • Sono facili da usare ed efficienti.
  • Non causeranno deadlock. Supponiamo che il mio task cron possa essere ucciso (potrebbe verificarsi un errore, oppure è troppo lungo e viene ucciso, e così via). In tal caso non eliminerà il semaforo, quindi tutte le attività future non funzioneranno. L'uso dei transienti risolve questo problema, perché dopo qualche tempo i transitori verranno eliminati.

E se ci fossero molte azioni diverse da fare?

Quindi supponiamo che ci siano molte attività cron diverse, che non dovrebbero mai essere eseguite contemporaneamente, ma vogliamo comunque che vengano eseguite tutte ...

Se utilizziamo la soluzione con semaforo e utilizziamo un solo semaforo per tutte queste attività, alcune potrebbero non funzionare mai. Quindi cosa fare allora?

In tal caso dovresti cambiare il tuo modo di pensare. Non hai alcune attività indipendenti, ma una fila di attività da svolgere. Quindi dovresti implementarlo in questo modo.

Così:

  1. È possibile aggiungere un tipo di coda (è possibile utilizzare un array e archiviarlo come opzione oppure aggiungere una tabella DB personalizzata).
  2. Si utilizza l'evento orario cron WP attualmente in uso per aggiungere attività alla coda.
  3. Aggiungete seconde attività cron WP che vengono eseguite molto più spesso e "mangiano" le attività dalla coda una alla volta. Questa attività "mangiatore" dovrebbe usare il semaforo per garantire che venga eseguita una sola attività alla volta.

Grazie, ma mi dispiace, non ho mai usato transitori prima ... Ma sto cercando di capire il codice. Perché hai impostato 5 minuti per il transitorio perché lo hai eliminato usando delete_transient(). Quindi quel momento conta? Voglio dire, ogni volta che ci metti set_transient, viene cancellato subito dopo che il mio lavoro è finito ... Allora perché c'è un tempo?
Sono la persona più stupida, il

Perché potrebbero verificarsi alcuni errori. Dai un'occhiata all'ultimo punto.
Krzysiek Dróżdż

Grazie, fantastico ... Solo una domanda. A quanto ho capito, se uso my_task_function_semaphorecome nome per il transitorio, devo usare tutti gli altri croni con lo stesso nome?
Sono la persona più stupida, il

@IamtheMostStupidPerson dipende da cosa vuoi raggiungere ... Se solo un'attività dovesse funzionare in un dato momento, allora sì - tutte le attività dovrebbero usare lo stesso nome transitorio del semaforo
Krzysiek Dróżdż

1
Ho fatto cose simili con gli strumenti di Job Queue come Gearman. Questa implementazione può aiutare: github.com/10up/WP-Minions
Fayaz
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.