该包的最新版本(1.0.0)没有可用的许可证信息。

允许PHP网络应用程序异步处理长时间运行的任务

1.0.0 2016-08-02 09:19 UTC

This package is auto-updated.

Last update: 2024-08-24 03:36:04 UTC


README

DJJob 允许PHP网络应用程序异步处理长时间运行的任务。它是 Shopify 开发的 delayed_job 的 PHP 端口,自 2010 年 4 月以来在 SeatGeek 的生产环境中使用。

与 delayed_job 一样,DJJob 使用一个 jobs 表来持久化和跟踪挂起、进行中和失败的任务。

要求

  • PHP5
  • PDO(PHP >= 5.1 内置)
  • (可选)PCNTL 库

设置

导入 sql 数据库表。

mysql db < jobs.sql

jobs 表的结构如下

CREATE TABLE `jobs` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
`handler` TEXT NOT NULL,
`queue` VARCHAR(255) NOT NULL DEFAULT 'default',
`attempts` INT UNSIGNED NOT NULL DEFAULT 0,
`run_at` DATETIME NULL,
`locked_at` DATETIME NULL,
`locked_by` VARCHAR(255) NULL,
`failed_at` DATETIME NULL,
`error` TEXT NULL,
`created_at` DATETIME NOT NULL
) ENGINE = INNODB;

如果传入的是序列化数据块而不是记录 ID,则可能需要将 handler 的列类型使用 BLOB。更多信息请见此链接。这种情况可能发生在以下错误中:unserialize(): Error at offset 2010 of 2425 bytes

告诉 DJJob 如何连接到您的数据库

DJJob::configure([
    'driver' => 'mysql',
    'host' => '127.0.0.1',
    'dbname' => 'djjob',
    'user' => 'root',
    'password' => 'topsecret',
]);

使用方法

任务是通过响应 perform 方法的 PHP 对象。任务被序列化并存储在数据库中。

<?php
// Job class
class HelloWorldJob {
    public function __construct($name) {
        $this->name = $name;
    }
    public function perform() {
        echo "Hello {$this->name}!\n";
    }
}

// enqueue a new job
DJJob::enqueue(new HelloWorldJob("delayed_job"));

与 delayed_job 不同,DJJob 没有任务优先级的概念(至少目前还没有)。相反,它支持多个队列。默认情况下,任务被放置在 "default" 队列中。您可以指定一个替代队列,例如

DJJob::enqueue(new SignupEmailJob("dev@seatgeek.com"), "email");

在 SeatGeek,我们运行一个针对特定电子邮件的队列。电子邮件有一个 sendLater 方法,它将任务放置在 email 队列中。以下是我们基本 Email 类的简化版本

class Email {
    public function __construct($recipient) {
        $this->recipient = $recipient;
    }
    public function send() {
        // do some expensive work to build the email: geolocation, etc..
        // use mail api to send this email
    }
    public function perform() {
        $this->send();
    }
    public function sendLater() {
        DJJob::enqueue($this, "email");
    }
}

因为 Email 有一个 perform 方法,所以电子邮件类的所有实例也都是任务。

运行任务

运行一个工作器非常简单

$worker = new DJWorker($options);
$worker->start();

初始化您的环境、连接到数据库等,由您决定。我们使用 symfony 的任务系统来运行工作器,以下是我们工作器任务的示例

<?php
class jobsWorkerTask extends sfPropelBaseTask {
  protected function configure() {
    $this->namespace        = 'jobs';
    $this->name             = 'worker';
    $this->briefDescription = '';
    $this->detailedDescription = <<<EOF
The [jobs:worker|INFO] task runs jobs created by the DJJob system.
Call it with:

  [php symfony jobs:worker|INFO]
EOF;
    $this->addArgument('application', sfCommandArgument::OPTIONAL, 'The application name', 'customer');
    $this->addOption('env', null, sfCommandOption::PARAMETER_REQUIRED, 'The environment', 'dev');
    $this->addOption('connection', null, sfCommandOption::PARAMETER_REQUIRED, 'The connection name', 'propel');
    $this->addOption('queue', null, sfCommandOption::PARAMETER_REQUIRED, 'The queue to pull jobs from', 'default');
    $this->addOption('count', null, sfCommandOption::PARAMETER_REQUIRED, 'The number of jobs to run before exiting (0 for unlimited)', 0);
    $this->addOption('sleep', null, sfCommandOption::PARAMETER_REQUIRED, 'Seconds to sleep after finding no new jobs', 5);
}

  protected function execute($arguments = array(), $options = array()) {
    // Database initialization
    $databaseManager = new sfDatabaseManager($this->configuration);
    $connection = Propel::getConnection($options['connection'] ? $options['connection'] : '');

    $worker = new DJWorker($options);
    $worker->start();
  }
}

如果数据库有任何连接问题,工作器将退出。我们使用 god 来管理我们的工作器,包括在它们因任何原因退出时重启它们。

变更

  • 通过切换到 PDO 消除了 Propel 依赖