使用cron创建非阻塞任务

时间:2018-03-13 作者:Cyclonecode

我正在写一个插件,它收集了一个相当大的提要。将从每个提要项创建一个自定义帖子。提要还可以包含从远程url上载的每个项目的图像。处理整个提要可能需要一些时间,因为我想在后台进行处理,所以我正在研究cron以实现这一点。目前我正在做这样的事情:

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);
}
以上这类工作,但我认为一定有更好的方法来做这类事情?例如,由于配置的cron任务将仅在页面加载时运行,因此如果没有访问者,任务可能不会按所需的时间间隔运行。

2 个回复
SO网友:swissspidy

例如,由于配置的cron任务将仅在页面加载时运行,因此如果没有访问者,任务可能不会按所需的时间间隔运行。

要防止这种情况,您需要use your operating system\'s task scheduler.

为此,您需要定义define(\'DISABLE_WP_CRON\', true); 在您的wp-config.php 文件之后,您将添加如下crontab配置:

/10 * * * * curl http://YOUR_SITE_URL/wp-cron.php > /dev/null 2>&1
此配置将调用http://YOUR_SITE_URL/wp-cron.php 每十分钟一次。此时计划的任务将被执行。

您还可以使用WP-CLI进行以下操作:

*/10 * * * * cd /var/www/example.com/htdocs; wp cron event run --due-now > /dev/null 2>&1

SO网友:GeeC

我也有一个类似的问题需要解决,因为这是插件开发,所以会弄乱wp配置。php或使用WP-CLI不是选项。我决定如下。

我的计划任务运行一个调用异步操作的函数,通过wp_remote_post.

if ( ! wp_next_scheduled( \'my_long_running_event\' ) ) {
    wp_schedule_event( $start_time, $recurrence, \'my_long_running_event\' );
}

add_action( \'my_long_running_event\', \'invoke_my_long_running_function\' );
function invoke_my_long_running_function() {
    $nonce = wp_create_nonce( \'my_nonce\' . \'my_action\' );
    $url = admin_url( \'admin-post.php\' );
    $args = array(
        \'method\'      => \'POST\',
        \'timeout\'     => 5,
        \'redirection\' => 5,
        \'blocking\'    => false,
        \'headers\'     => array(),
        \'body\'        => array(
            \'action\'   => \'my_long_running_action\',
            \'my_nonce\' => $nonce,
        ),
    );
    return wp_remote_post( $url, $args );
}

最重要的部分是\'blocking\' => false 因为这会异步运行操作。

nonce的使用是可选的,但有助于防止直接调用长时间运行的函数。如果您需要在日程安排之外打电话,请打电话给您的对等人员invoke_my_long_running_function() 相反

然后,您需要一个admin\\u post-action挂钩来实际/最终运行您的函数。

add_action( \'admin_post_nopriv_my_long_running_action\', \'my_long_running_function\' );
使用nopriv 不理想,但计划的作业未经过身份验证,因此nopriv 是必需的,否则操作将无法运行。

当然,你还需要my_long_running_function.

function my_long_running_function() {
    // Do the heavy work here.
}

结束

相关推荐

自定义循环不起作用/WP Cron事件

我创建了一个wp cron事件,自定义间隔为5分钟,但它只每小时执行一次,而不是每5分钟执行一次。(回调已正确执行。)DISABLE\\u WP\\u CRON常量设置为true,WP CRON。php每5分钟通过crontab调用一次。(https://developer.wordpress.org/plugins/cron/hooking-into-the-system-task-scheduler/)调试中没有错误。日志(WP\\u DEBUG设置为true)。我用wordpress插件boilde