0

I'm writing a plugin which collects a pretty large feed. From each feed item a custom post will be created. The feed can also contain images for each item that is uploaded from the remote url. Processing the entire feed can take some time and since I would like to do the processing in the background I am looking into cron as a way to achieve this. Currently I'm doing something like this:

class Cron_Task {
  const DEFAULT_TASK_INTERVAL = 30;

  public function __construct($taskName, $data) {
    add_filter('cron_schedules', array($this, 'addSchedule'));
    add_action('cron_task', 'Cron_Task::run');
    if (!wp_next_scheduled('cron_task', array($taskName))) {
      // Store data in cache.
      set_transient($taskName, serialize($data));
      wp_schedule_event(time(), $taskName, 'cron_task', array($taskName));
    }
  }

  public static function processItem($data) {
    // Execute long running task.
  }

  public function addSchedule($schedules) {
    $schedules['crontask'] = array(
      'interval' => self::DEFAULT_TASK_INTERVAL,
      'display' => __('Cron_Task'),
    );
    return $schedules;
  }

  public static function run($taskName) {
    // Get data from cache.
    $data = unserialize(get_transient($taskName));
    if ($data) {
      $item = array_shift($data);
      // Process one item.
      self::processItem($item);

      // Check if we have processed all items.
      if (!count($data)) {
        delete_transient($taskName);
        wp_clear_scheduled_hook('cron_task', array($taskName));
      } else {
        // Update the items to process.
        set_transient($taskName, serialize($data));
      }
    }

  }
}

// When a feed is collected we create a cron_task to be run every 30 seconds.
if (get_feed()) {
  $cronTask = new Cron_Task('testEvent', $feed);
}

The above sort of works, but I think there must be a better way of doing this kind of thing? For instance, since the configured cron tasks will only be run on page load, the task might not be run at the desired interval if there are no visitors.

  • if there is no traffic why do you care that the site is not up to date? (serious question, not trying to troll) – Mark Kaplun Mar 13 '18 at 10:22
  • @MarkKaplun - This is more a question how to perform async tasks at certain intervals in wordpress. I only wrote that there might be no visitors to pin point the problem in this case. – Cyclonecode Mar 13 '18 at 10:50
  • if you write a plugin, wordpress cron is the only tool you can be sure to be there. @swissspidy answer is good way to avoid the "no traffic" issue, but it should be fun to make site owners to properly configure it, and totally rare for them to even have access to wpcli – Mark Kaplun Mar 13 '18 at 10:55
  • .... and as I commented of his answer I believe the best way to go is with you supplying wpcli integration in your plugin. and then, those that can, will be able to trigger the update any way they will want. – Mark Kaplun Mar 13 '18 at 10:57
  • @MarkKaplun - If you simply would like to call wp-cron.php at a regular interval then the simplest way would be to just add a new cron job using crontab -e =) This question is like I said more about a good way to implement async tasks, like this project: github.com/techcrunch/wp-async-task – Cyclonecode Mar 13 '18 at 11:09
1

For instance, since the configured cron tasks will only be run on page load, the task might not be run at the desired interval if there are no visitors.

To prevent this, you need to use your operating system's task scheduler.

For this, you need to define define('DISABLE_WP_CRON', true); in your wp-config.php file. After that, you'd add a crontab configuration like this:

/10 * * * * curl http://YOUR_SITE_URL/wp-cron.php > /dev/null 2>&1

This configuration would call http://YOUR_SITE_URL/wp-cron.php every ten minutes. Tasks that are scheduled at this point will be executed.

You can also use WP-CLI for that:

*/10 * * * * cd /var/www/example.com/htdocs; wp cron event run --due-now > /dev/null 2>&1
  • 2
    The problem is that if the processing is hard, and takes a long time you will have to split the handling, and if you split it to let say 6 segments, the "import" will take an hour. OTOH wp-cli is much better option to escape the web server limitations, but instead of fighting with wordpress cron I would just implement a command for wp-cli – Mark Kaplun Mar 13 '18 at 10:26
  • 2
    hmmm and since he is doing a plugin, probably implementing any of this options is not up to him. – Mark Kaplun Mar 13 '18 at 10:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.