elvetemedve / djjob
允许PHP网络应用程序异步处理长时间运行的任务
Requires
- php: >=5.1.0
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 依赖