Compare commits

..

No commits in common. "main" and "1.4.3" have entirely different histories.
main ... 1.4.3

61 changed files with 1356 additions and 3780 deletions

View file

@ -1,36 +0,0 @@
name: CI
on: [push]
jobs:
Linter:
runs-on: ubuntu-latest
container: php:8.2
steps:
- uses: actions/checkout@v3
- name: Install composer
run: apt-get update -yq && apt-get install git wget procps unzip -y && pecl install -o -f redis && rm -rf /tmp/pear && docker-php-ext-enable redis && wget https://getcomposer.org/composer.phar && php composer.phar install --dev
- name: Validate composer.json and composer.lock
run: php composer.phar validate --strict
- name: Install dependencies
run: php composer.phar install --dev --prefer-dist --no-progress
- name: Run PHPCS Linter
run: php -d memory_limit=256M vendor/bin/phpcs -s --standard=ruleset.xml
PHPTest:
runs-on: ubuntu-latest
container: php:${{ matrix.php_version }}
strategy:
matrix:
php_version: [8.1, 8.2,8.3,8.4]
services:
redis:
image: redis:7.0
options: >-
--health-cmd "redis-cli ping"
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
- uses: actions/checkout@v3
- name: Install composer
run: apt-get update -yq && apt-get install git wget procps unzip -y && pecl install -o -f redis && rm -rf /tmp/pear && docker-php-ext-enable redis && wget https://getcomposer.org/composer.phar && php composer.phar install --dev
- name: Run PHP ${{ matrix.php_version }}} Unit Tests
run: php vendor/bin/phpunit --verbose --configuration phpunit.xml

3
.gitignore vendored
View file

@ -1,2 +1,3 @@
vendor/ vendor/
.phpunit.result.cache *.swp
phpunit.xml

View file

@ -1,43 +0,0 @@
.docker_boostrap: &docker_boostrap |
[[ ! -e /.dockerenv ]] && exit 0
set -xe
# Install git (the php image doesn't have it) which is required by composer
apt-get update -yq
apt-get install git wget procps unzip -y
# Install pcntl and redis extentions
pecl install -o -f redis \
&& rm -rf /tmp/pear \
&& docker-php-ext-enable redis
docker-php-ext-install pcntl
# Install Composer
wget https://getcomposer.org/composer.phar
php composer.phar install --dev
services:
- redis:7
# Test PHP
test:
image: php:$PHP_VERSION
parallel:
matrix:
- PHP_VERSION: [ "7.4", "8.0", "8.1", "8.2" ]
before_script:
- *docker_boostrap
script:
- php vendor/bin/phpunit --verbose --configuration phpunit.xml
tags:
- docker
# Codestandards
lint:
image: php:8.2
allow_failure: true
script:
- apt update && apt install -y wget unzip git
- wget https://getcomposer.org/composer.phar
- php composer.phar install --dev
- php -d memory_limit=256M vendor/bin/phpcs -s --standard=ruleset.xml

13
.travis.yml Normal file
View file

@ -0,0 +1,13 @@
language: php
php:
- 7.0
- 7.1
- 7.2
services:
- redis-server
before_script:
- echo "extension = redis.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini
- composer install

View file

@ -1,75 +1,3 @@
# 2.5.3 (2025-06-08)
- Update typing of Log() to support all psr\log versions
- # 2.5.2 (2025-06-08)
- Update typing of Log() to support all psr\log versions
# 2.5.1 (2025-06-08)
- Update psr/log version requirements
# 2.5.0 (2025-06-08)
- Update packages
# 2.4.0 (2024-12-11)
- Update packages (psr/log ^3.0.2)
# 2.3.0 (2024-09-04)
- Update packages
# 2.2.0 (2023-03-20)
- Update pacakges
- Bump requirements to PHP >= 8.1
# 2.1.3 (2023-11-15)
- Resolved issue with SET EX TTL's using unix-timestamps
# 2.1.2 (2023-03-22)
- Update composer packages
- Update git information (GitHub)
# 2.1.1 (2023-03-20)
- Changed setex to set with EX values
- Added TTLs to missing keys
## 2.1.0 (2023-02-07)
- Add PHP 8.1 / 8.2 unit tests
- Updated code to be PHP 8.2 compliant
## 2.0.3 (2022-09-12)
- Update composer packages
- Added WoodpeckerCI tests
- Updated links in composer package
- Stricter typing
## 2.0.2 (2022-02-15)
- Replace strftime with strtotime for PHP8.1 support
- Added processing class into proc line for easier debugging
## 2.0.1 (2022-02-08)
- Fixed issue with lingering keys causing constant memory growth
- Add PHP8 support
- Composer upgrade
## 2.0.0 (2021-02-19)
- Moved to PSR-4
- Namespaced codebase
- Added more comments throughout
## 1.4.7 (2020-04-11)
- Update PHPUnit to 9
- Start adding return types
## 1.4.6 (2020-01-10)
- Switched IF Statement order to prevent excess calls to redis.
## 1.4.5 (2019-08-28)
- Added 'replaced' composer tag.
- Formatting changes.
## 1.4.4 (2019-06-02)
- Updated tests to run on GitLab CI.
- Can now run tests locally using `gitlab-runner exec docker test:7.0`
## 1.4.3 (2018-07-16) ## 1.4.3 (2018-07-16)
- Updated README to include supervisor configuration. - Updated README to include supervisor configuration.
- Change logfile date format to `%Y-%m-%d %T`. - Change logfile date format to `%Y-%m-%d %T`.
@ -150,7 +78,7 @@ Changes by iskandar introduce improved support for using DSNs to connect to Redi
* Pass queue name to afterEvent callback * Pass queue name to afterEvent callback
* Only declare RedisException if it doesn't already exist (Matt Heath) * Only declare RedisException if it doesn't already exist (Matt Heath)
* Add support for Composer * Add support for Composer
* Fix missing and incorrect paths for Resque and \Resque\Job\Status classes in demo (jjfrey) * Fix missing and incorrect paths for Resque and Resque_Job_Status classes in demo (jjfrey)
* Disable autoload for the RedisException class_exists call (scragg0x) * Disable autoload for the RedisException class_exists call (scragg0x)
* General tidy up of comments and files/folders * General tidy up of comments and files/folders

View file

@ -14,9 +14,9 @@ What happens when you call `Resque::enqueue()`?
4. `Resque_Job::create()` pushes the job to the requested queue (first 4. `Resque_Job::create()` pushes the job to the requested queue (first
argument) argument)
5. `Resque_Job::create()`, if status monitoring is enabled for the job (fourth 5. `Resque_Job::create()`, if status monitoring is enabled for the job (fourth
argument), calls `\Resque\Job\Status::create()` with the job ID as its only argument), calls `Resque_Job_Status::create()` with the job ID as its only
argument argument
6. `\Resque\Job\Status::create()` creates a key in Redis with the job ID in its 6. `Resque_Job_Status::create()` creates a key in Redis with the job ID in its
name, and the current status (as well as a couple of timestamps) as its name, and the current status (as well as a couple of timestamps) as its
value, then returns control to `Resque_Job::create()` value, then returns control to `Resque_Job::create()`
7. `Resque_Job::create()` returns control to `Resque::enqueue()`, with the job 7. `Resque_Job::create()` returns control to `Resque::enqueue()`, with the job
@ -85,15 +85,15 @@ How do the workers process the queues?
* Worker * Worker
1. The worker waits for the job process to complete 1. The worker waits for the job process to complete
2. If the exit status is not 0, the worker calls `Resque_Job->fail()` with 2. If the exit status is not 0, the worker calls `Resque_Job->fail()` with
a `Resque\Job\DirtyExitException` as its only argument. a `Resque_Job_DirtyExitException` as its only argument.
3. `Resque_Job->fail()` triggers an `onFailure` event 3. `Resque_Job->fail()` triggers an `onFailure` event
4. `Resque_Job->fail()` updates the job status from `RUNNING` to `FAILED` 4. `Resque_Job->fail()` updates the job status from `RUNNING` to `FAILED`
5. `Resque_Job->fail()` calls `Resque_Failure::create()` with the job 5. `Resque_Job->fail()` calls `Resque_Failure::create()` with the job
payload, the `Resque\Job\DirtyExitException`, the internal ID of the payload, the `Resque_Job_DirtyExitException`, the internal ID of the
worker, and the queue name as arguments worker, and the queue name as arguments
6. `Resque_Failure::create()` creates a new object of whatever type has 6. `Resque_Failure::create()` creates a new object of whatever type has
been set as the `Resque_Failure` "backend" handler; by default, this is been set as the `Resque_Failure` "backend" handler; by default, this is
a `ResqueFailureRedis` object, whose constructor simply collects the a `Resque_Failure_Redis` object, whose constructor simply collects the
data passed into `Resque_Failure::create()` and pushes it into Redis data passed into `Resque_Failure::create()` and pushes it into Redis
in the `failed` queue in the `failed` queue
7. `Resque_Job->fail()` increments two failure counters in Redis: one for 7. `Resque_Job->fail()` increments two failure counters in Redis: one for

View file

@ -1,4 +1,4 @@
php-resque: PHP Background (Resque) Worker php-resque: PHP Resque Worker (and Enqueue) [![Build Status](https://travis-ci.org/iDanoo/php-resque.svg?branch=master)](https://travis-ci.org/iDanoo/php-resque)
=========================================== ===========================================
Resque is a Redis-backed library for creating background jobs, placing Resque is a Redis-backed library for creating background jobs, placing
@ -34,15 +34,9 @@ not exit with a status code as 0
* Has built in support for `setUp` and `tearDown` methods, called * Has built in support for `setUp` and `tearDown` methods, called
pre and post jobs pre and post jobs
On top of the original fork (chrisboulton/php-resque) I have added:
* Custom log levels
* PHP7.0+ compatibility
## Requirements ## ## Requirements ##
* PHP 8.1+ * PHP 7.0+ (May work with 5.6+, Untested)
* phpredis * phpredis
* Redis 2.2+ * Redis 2.2+
@ -53,9 +47,19 @@ Composer package inside your project.
If you're not familiar with Composer, please see <http://getcomposer.org/>. If you're not familiar with Composer, please see <http://getcomposer.org/>.
1. Run `composer require idanoo/php-resque`. 1. Add php-resque to your application's composer.json.
2. If you haven't already, add the Composer autoload to your project's ```json
{
"require": {
"idanoo/php-resque": "^1.4"
}
}
```
2. Run `composer install`.
3. If you haven't already, add the Composer autoload to your project's
initialization file. (example) initialization file. (example)
```sh ```sh
@ -70,11 +74,11 @@ Jobs are queued as follows:
```php ```php
// Required if redis is located elsewhere // Required if redis is located elsewhere
Resque::setBackend('redis:6379'); Resque::setBackend('localhost:6379');
$args = ['name' => 'TestName']; $args = ['name' => 'TestName'];
Resque::enqueue('default', '\App\MyJobClass', $args); Resque::enqueue('default', 'My_Job', $args);
``` ```
### Defining Jobs ### ### Defining Jobs ###
@ -82,9 +86,7 @@ Resque::enqueue('default', '\App\MyJobClass', $args);
Each job should be in its own class, and include a `perform` method. Each job should be in its own class, and include a `perform` method.
```php ```php
namespace \App; class My_Job
class MyJobClass
{ {
public function perform() public function perform()
{ {
@ -107,9 +109,7 @@ The `tearDown` method, if defined, will be called after the job finishes.
```php ```php
namespace App; class My_Job
class MyJobClass
{ {
public function setUp() public function setUp()
{ {
@ -133,17 +133,17 @@ class MyJobClass
This method can be used to conveniently remove a job from a queue. This method can be used to conveniently remove a job from a queue.
```php ```php
// Removes job class '\App\MyJobClass' of queue 'default' // Removes job class 'My_Job' of queue 'default'
Resque::dequeue('default', ['\App\MyJobClass']); Resque::dequeue('default', ['My_Job']);
// Removes job class '\App\MyJobClass' with Job ID '087df5819a790ac666c9608e2234b21e' of queue 'default' // Removes job class 'My_Job' with Job ID '087df5819a790ac666c9608e2234b21e' of queue 'default'
Resque::dequeue('default', ['\App\MyJobClass' => '087df5819a790ac666c9608e2234b21e']); Resque::dequeue('default', ['My_Job' => '087df5819a790ac666c9608e2234b21e']);
// Removes job class '\App\MyJobClass' with arguments of queue 'default' // Removes job class 'My_Job' with arguments of queue 'default'
Resque::dequeue('default', ['\App\MyJobClass' => ['foo' => 1, 'bar' => 2]]); Resque::dequeue('default', ['My_Job' => ['foo' => 1, 'bar' => 2]]);
// Removes multiple jobs // Removes multiple jobs
Resque::dequeue('default', ['\App\MyJobClass', '\App\MyJobClass2']); Resque::dequeue('default', ['My_Job', 'My_Job2']);
``` ```
If no jobs are given, this method will dequeue all jobs matching the provided queue. If no jobs are given, this method will dequeue all jobs matching the provided queue.
@ -164,7 +164,7 @@ To track the status of a job, pass `true` as the fourth argument to
returned: returned:
```php ```php
$token = Resque::enqueue('default', '\App\MyJobClass', $args, true); $token = Resque::enqueue('default', 'My_Job', $args, true);
echo $token; echo $token;
``` ```
@ -361,6 +361,8 @@ your `APP_INCLUDE` script should initialize and register any listeners required
for operation. If you have rolled your own worker manager, then it is again your for operation. If you have rolled your own worker manager, then it is again your
responsibility to register listeners. responsibility to register listeners.
A sample plugin is included in the `extras` directory.
### Events ### ### Events ###
#### beforeFirstFork #### #### beforeFirstFork ####
@ -462,7 +464,7 @@ needing to directly examine the code), have a look at `HOWITWORKS.md`.
## Contributors ## ## Contributors ##
### Current Maintainers ### ### Current Maintainers ###
* @idanoo * @iDanoo
### Past Maintainer / Forked From ### ### Past Maintainer / Forked From ###

View file

@ -9,6 +9,7 @@ $files = [
__DIR__ . '/../vendor/autoload.php', __DIR__ . '/../vendor/autoload.php',
]; ];
$found = false;
foreach ($files as $file) { foreach ($files as $file) {
if (file_exists($file)) { if (file_exists($file)) {
require_once $file; require_once $file;
@ -24,7 +25,6 @@ if (!class_exists('Composer\Autoload\ClassLoader', false)) {
); );
} }
// Set which queues to monitor '*'
$QUEUE = getenv('QUEUE'); $QUEUE = getenv('QUEUE');
if (empty($QUEUE)) { if (empty($QUEUE)) {
die("Set QUEUE env var containing the list of queues to work.\n"); die("Set QUEUE env var containing the list of queues to work.\n");
@ -38,26 +38,22 @@ if (empty($QUEUE)) {
*/ */
$REDIS_BACKEND = getenv('REDIS_BACKEND'); $REDIS_BACKEND = getenv('REDIS_BACKEND');
/** // A redis database number
* REDIS_BACKEND_DB overrides default Redis DB
*/
$REDIS_BACKEND_DB = getenv('REDIS_BACKEND_DB'); $REDIS_BACKEND_DB = getenv('REDIS_BACKEND_DB');
if (!empty($REDIS_BACKEND)) { if (!empty($REDIS_BACKEND)) {
if (empty($REDIS_BACKEND_DB)) { if (empty($REDIS_BACKEND_DB)) {
\Resque\Resque::setBackend($REDIS_BACKEND); Resque::setBackend($REDIS_BACKEND);
} else { } else {
\Resque\Resque::setBackend($REDIS_BACKEND, $REDIS_BACKEND_DB); Resque::setBackend($REDIS_BACKEND, $REDIS_BACKEND_DB);
} }
} }
// Set Logging level
$logLevel = false; $logLevel = false;
$LOGGING = getenv('LOGLEVEL'); $LOGGING = getenv('LOGLEVEL');
if (!empty($LOGGING)) { if (!empty($LOGGING)) {
$logLevel = $LOGGING; $logLevel = $LOGGING;
} }
// Bootstrap file
$APP_INCLUDE = getenv('APP_INCLUDE'); $APP_INCLUDE = getenv('APP_INCLUDE');
if ($APP_INCLUDE) { if ($APP_INCLUDE) {
if (!file_exists($APP_INCLUDE)) { if (!file_exists($APP_INCLUDE)) {
@ -70,45 +66,41 @@ if ($APP_INCLUDE) {
// See if the APP_INCLUDE containes a logger object, // See if the APP_INCLUDE containes a logger object,
// If none exists, fallback to internal logger // If none exists, fallback to internal logger
if (!isset($logger) || !is_object($logger)) { if (!isset($logger) || !is_object($logger)) {
$logger = new \Resque\Log($logLevel); $logger = new Resque_Log($logLevel);
} }
// Determines if blocking or not
$BLOCKING = getenv('BLOCKING') !== FALSE; $BLOCKING = getenv('BLOCKING') !== FALSE;
// Interval to check for jobs
$interval = 5; $interval = 5;
$INTERVAL = getenv('INTERVAL'); $INTERVAL = getenv('INTERVAL');
if (!empty($INTERVAL)) { if (!empty($INTERVAL)) {
$interval = $INTERVAL; $interval = $INTERVAL;
} }
// Sets worker count
$count = 1; $count = 1;
$COUNT = getenv('COUNT'); $COUNT = getenv('COUNT');
if (!empty($COUNT) && $COUNT > 1) { if (!empty($COUNT) && $COUNT > 1) {
$count = $COUNT; $count = $COUNT;
} }
// Determines redis key prefix
$PREFIX = getenv('PREFIX'); $PREFIX = getenv('PREFIX');
if (!empty($PREFIX)) { if (!empty($PREFIX)) {
$logger->log(\Psr\Log\LogLevel::INFO, 'Prefix set to {prefix}', ['prefix' => $PREFIX]); $logger->log(Psr\Log\LogLevel::INFO, 'Prefix set to {prefix}', ['prefix' => $PREFIX]);
\Resque\Redis::prefix($PREFIX); Resque_Redis::prefix($PREFIX);
} }
if ($count > 1) { if ($count > 1) {
for ($i = 0; $i < $count; ++$i) { for ($i = 0; $i < $count; ++$i) {
$pid = \Resque\Resque::fork(); $pid = Resque::fork();
if ($pid === false || $pid === -1) { if ($pid === false || $pid === -1) {
$logger->log(\Psr\Log\LogLevel::EMERGENCY, 'Could not fork worker {count}', ['count' => $i]); $logger->log(Psr\Log\LogLevel::EMERGENCY, 'Could not fork worker {count}', ['count' => $i]);
die(); die();
} elseif (!$pid) { } elseif (!$pid) {
// Child, start the worker // Child, start the worker
$queues = explode(',', $QUEUE); $queues = explode(',', $QUEUE);
$worker = new \Resque\Worker($queues); $worker = new Resque_Worker($queues);
$worker->setLogger($logger); $worker->setLogger($logger);
$logger->log(\Psr\Log\LogLevel::NOTICE, 'Starting worker {worker}', ['worker' => $worker]); $logger->log(Psr\Log\LogLevel::NOTICE, 'Starting worker {worker}', ['worker' => $worker]);
$worker->work($interval, $BLOCKING); $worker->work($interval, $BLOCKING);
break; break;
} }
@ -116,7 +108,7 @@ if ($count > 1) {
} else { } else {
// Start a single worker // Start a single worker
$queues = explode(',', $QUEUE); $queues = explode(',', $QUEUE);
$worker = new \Resque\Worker($queues); $worker = new Resque_Worker($queues);
$worker->setLogger($logger); $worker->setLogger($logger);
$PIDFILE = getenv('PIDFILE'); $PIDFILE = getenv('PIDFILE');
@ -125,6 +117,6 @@ if ($count > 1) {
die('Could not write PID information to ' . $PIDFILE); die('Could not write PID information to ' . $PIDFILE);
} }
$logger->log(\Psr\Log\LogLevel::NOTICE, 'Starting worker {worker}', ['worker' => $worker]); $logger->log(Psr\Log\LogLevel::NOTICE, 'Starting worker {worker}', ['worker' => $worker]);
$worker->work($interval, $BLOCKING); $worker->work($interval, $BLOCKING);
} }

18
build.xml Normal file
View file

@ -0,0 +1,18 @@
<!--suppress PhingDomInspection -->
<project name="php-resque" default="build">
<target name="clean">
<delete dir="${basedir}/build" />
</target>
<target name="prepare">
<mkdir dir="${basedir}/build" />
<mkdir dir="${basedir}/build/logs" />
</target>
<target name="phpunit">
<exec dir="${basedir}" executable="phpunit">
<arg line="--log-junit ${basedir}/build/logs/phpunit.xml
--coverage-clover ${basedir}/build/logs/clover.xml
--coverage-html ${basedir}/build/coverage" />
</exec>
</target>
<target name="build" depends="clean,prepare,phpunit" />
</project>

View file

@ -1,13 +1,10 @@
{ {
"name": "idanoo/php-resque", "name": "idanoo/php-resque",
"version": "1.4.3",
"type": "library", "type": "library",
"replace": {
"chrisboulton/php-resque": "*",
"danhunsaker/php-resque": "*"
},
"description": "Redis backed library for creating background jobs and processing them later. Based on resque for Ruby. Originally forked from chrisboulton/php-resque.", "description": "Redis backed library for creating background jobs and processing them later. Based on resque for Ruby. Originally forked from chrisboulton/php-resque.",
"keywords": ["job", "background", "redis", "resque", "php"], "keywords": ["job", "background", "redis", "resque"],
"homepage": "https://github.com/idanoo/php-resque", "homepage": "http://www.github.com/idanoo/php-resque/",
"license": "MIT", "license": "MIT",
"authors": [ "authors": [
{ {
@ -16,36 +13,25 @@
} }
], ],
"require": { "require": {
"php": ">=8.1", "php": "^7.0",
"psr/log": "^1.1 || ^2.0 || ^3.0", "ext-pcntl": "*",
"colinmollenhour/credis": "^1.14.0" "ext-redis": "*",
"psr/log": "~1.0",
"colinmollenhour/credis": "^1.10"
}, },
"require-dev": { "require-dev": {
"phpunit/phpunit": "^9", "phpunit/phpunit": "^6"
"squizlabs/php_codesniffer": "3.*",
"phpcompatibility/php-compatibility": "^9.3",
"dealerdirect/phpcodesniffer-composer-installer": "^1.0"
}, },
"bin": [ "bin": [
"bin/resque" "bin/resque"
], ],
"autoload": { "autoload": {
"psr-4": { "psr-0": {
"Resque\\": "src/Resque" "Resque": "lib"
}
},
"autoload-dev": {
"psr-4": {
"Resque\\Test\\": "tests/Resque/Tests"
} }
}, },
"support": { "support": {
"issues": "https://github.com/idanoo/php-resque/issues", "issues": "https://github.com/idanoo/php-resque/issues",
"source": "https://github.com/idanoo/php-resque" "source": "https://github.com/idanoo/php-resque"
},
"config": {
"allow-plugins": {
"dealerdirect/phpcodesniffer-composer-installer": true
}
} }
} }

2092
composer.lock generated

File diff suppressed because it is too large Load diff

8
demo/bad_job.php Normal file
View file

@ -0,0 +1,8 @@
<?php
class Bad_PHP_Job
{
public function perform()
{
throw new Exception('Unable to run this job!');
}
}

View file

@ -1,7 +1,4 @@
<?php <?php
namespace Resque\Example;
if (empty($argv[1])) { if (empty($argv[1])) {
die('Specify the ID of a job to monitor the status of.'); die('Specify the ID of a job to monitor the status of.');
} }
@ -9,12 +6,12 @@ if (empty($argv[1])) {
require __DIR__ . '/init.php'; require __DIR__ . '/init.php';
date_default_timezone_set('GMT'); date_default_timezone_set('GMT');
\Resque\Resque::setBackend('127.0.0.1:6379'); Resque::setBackend('127.0.0.1:6379');
// You can also use a DSN-style format: // You can also use a DSN-style format:
//Resque::setBackend('redis://user:pass@127.0.0.1:6379'); //Resque::setBackend('redis://user:pass@127.0.0.1:6379');
//Resque::setBackend('redis://user:pass@a.host.name:3432/2'); //Resque::setBackend('redis://user:pass@a.host.name:3432/2');
$status = new \Resque\Job\Status($argv[1]); $status = new Resque_Job_Status($argv[1]);
if (!$status->isTracking()) { if (!$status->isTracking()) {
die("Resque is not tracking the status of this job.\n"); die("Resque is not tracking the status of this job.\n");
} }
@ -23,4 +20,4 @@ echo "Tracking status of " . $argv[1] . ". Press [break] to stop.\n\n";
while (true) { while (true) {
fwrite(STDOUT, "Status of " . $argv[1] . " is: " . $status->get() . "\n"); fwrite(STDOUT, "Status of " . $argv[1] . " is: " . $status->get() . "\n");
sleep(1); sleep(1);
} }

View file

@ -1,7 +1,4 @@
<?php <?php
namespace Resque\Example;
// Find and initialize Composer // Find and initialize Composer
// NOTE: You should NOT use this when developing against php-resque. // NOTE: You should NOT use this when developing against php-resque.
// The autoload code below is specifically for this demo. // The autoload code below is specifically for this demo.
@ -11,6 +8,7 @@ $files = [
__DIR__ . '/../vendor/autoload.php', __DIR__ . '/../vendor/autoload.php',
]; ];
$found = false;
foreach ($files as $file) { foreach ($files as $file) {
if (file_exists($file)) { if (file_exists($file)) {
require_once $file; require_once $file;
@ -24,4 +22,4 @@ if (!class_exists('Composer\Autoload\ClassLoader', false)) {
'curl -s http://getcomposer.org/installer | php' . PHP_EOL . 'curl -s http://getcomposer.org/installer | php' . PHP_EOL .
'php composer.phar install' . PHP_EOL 'php composer.phar install' . PHP_EOL
); );
} }

View file

@ -1,8 +1,6 @@
<?php <?php
namespace Resque\Example; class PHP_Job
class PHPJob
{ {
public function perform() public function perform()
{ {
@ -10,4 +8,4 @@ class PHPJob
sleep(1); sleep(1);
fwrite(STDOUT, 'Job ended!' . PHP_EOL); fwrite(STDOUT, 'Job ended!' . PHP_EOL);
} }
} }

View file

@ -1,11 +1,9 @@
<?php <?php
namespace Resque\Example; class Long_PHP_Job
class LongPHPJob
{ {
public function perform() public function perform()
{ {
sleep(600); sleep(600);
} }
} }

9
demo/php_error_job.php Normal file
View file

@ -0,0 +1,9 @@
<?php /** @noinspection PhpUndefinedFunctionInspection */
class PHP_Error_Job
{
public function perform()
{
callToUndefinedFunction();
}
}

View file

@ -1,14 +1,11 @@
<?php <?php
namespace Resque\Example;
if (empty($argv[1])) { if (empty($argv[1])) {
die('Specify the name of a job to add. e.g, php queue.php PHPJob'); die('Specify the name of a job to add. e.g, php queue.php PHP_Job');
} }
require __DIR__ . '/init.php'; require __DIR__ . '/init.php';
date_default_timezone_set('GMT'); date_default_timezone_set('GMT');
\Resque\Resque::setBackend('127.0.0.1:6379'); Resque::setBackend('127.0.0.1:6379');
// You can also use a DSN-style format: // You can also use a DSN-style format:
//Resque::setBackend('redis://user:pass@127.0.0.1:6379'); //Resque::setBackend('redis://user:pass@127.0.0.1:6379');
@ -21,9 +18,9 @@ $args = [
], ],
]; ];
if (empty($argv[2])) { if (empty($argv[2])) {
$jobId = \Resque\Resque::enqueue('default', $argv[1], $args, true); $jobId = Resque::enqueue('default', $argv[1], $args, true);
} else { } else {
$jobId = \Resque\Resque::enqueue($argv[1], $argv[2], $args, true); $jobId = Resque::enqueue($argv[1], $argv[2], $args, true);
} }
echo "Queued job " . $jobId . "\n\n"; echo "Queued job " . $jobId . "\n\n";

7
demo/resque.php Normal file
View file

@ -0,0 +1,7 @@
<?php
date_default_timezone_set('GMT');
require 'bad_job.php';
require 'job.php';
require 'php_error_job.php';
require '../bin/resque';

View file

@ -1,11 +0,0 @@
<?php
namespace Resque\Example;
class BadPHPJob
{
public function perform()
{
throw new \Exception('Unable to run this job!');
}
}

View file

@ -1,13 +0,0 @@
<?php
/** @noinspection PhpUndefinedFunctionInspection */
namespace Resque\Example;
class PHPErrorJob
{
public function perform()
{
callToUndefinedFunction();
}
}

View file

@ -5,6 +5,6 @@
compress compress
compressoptions -4 compressoptions -4
notifempty notifempty
create 640 root www-data create 640 root adm
copytruncate copytruncate
} }

15
extras/resque.monit Normal file
View file

@ -0,0 +1,15 @@
# Borrowed with modifications from
# https://github.com/defunkt/resque/blob/master/examples/monit/resque.monit
# Replace these with your own:
# [QUEUE]
# [PATH/TO/RESQUE]
# [UID]
# [GID]
# [APP_INCLUDE]
check process resque_worker_[QUEUE]
with pidfile /var/run/resque/worker_[QUEUE].pid
start program = "/bin/sh -c 'APP_INCLUDE=[APP_INCLUDE] QUEUE=[QUEUE] VERBOSE=1 PIDFILE=/var/run/resque/worker_[QUEUE].pid nohup php -f [PATH/TO/RESQUE]/bin/resque > /var/log/resque/worker_[QUEUE].log &'" as uid [UID] and gid [GID]
stop program = "/bin/sh -c 'kill -s QUIT `cat /var/run/resque/worker_[QUEUE].pid` && rm -f /var/run/resque/worker_[QUEUE].pid; exit 0;'"
if totalmem is greater than 300 MB for 10 cycles then restart # eating up memory?
group resque_workers

View file

@ -1,17 +1,14 @@
<?php <?php
namespace Resque\Example;
// Somewhere in our application, we need to register: // Somewhere in our application, we need to register:
// \Resque\Event::listen('afterEnqueue', ['My_Resque_Plugin', 'afterEnqueue']); Resque_Event::listen('afterEnqueue', ['My_Resque_Plugin', 'afterEnqueue']);
// \Resque\Event::listen('beforeFirstFork', ['My_Resque_Plugin', 'beforeFirstFork']); Resque_Event::listen('beforeFirstFork', ['My_Resque_Plugin', 'beforeFirstFork']);
// \Resque\Event::listen('beforeFork', ['My_Resque_Plugin', 'beforeFork']); Resque_Event::listen('beforeFork', ['My_Resque_Plugin', 'beforeFork']);
// \Resque\Event::listen('afterFork', ['My_Resque_Plugin', 'afterFork']); Resque_Event::listen('afterFork', ['My_Resque_Plugin', 'afterFork']);
// \Resque\Event::listen('beforePerform', ['My_Resque_Plugin', 'beforePerform']); Resque_Event::listen('beforePerform', ['My_Resque_Plugin', 'beforePerform']);
// \Resque\Event::listen('afterPerform', ['My_Resque_Plugin', 'afterPerform']); Resque_Event::listen('afterPerform', ['My_Resque_Plugin', 'afterPerform']);
// \Resque\Event::listen('onFailure', ['My_Resque_Plugin', 'onFailure']); Resque_Event::listen('onFailure', ['My_Resque_Plugin', 'onFailure']);
class SampleResquePlugin class Sample_Resque_Plugin
{ {
public static function afterEnqueue($class, $arguments) public static function afterEnqueue($class, $arguments)
{ {
@ -37,7 +34,7 @@ class SampleResquePlugin
public static function beforePerform($job) public static function beforePerform($job)
{ {
echo "Cancelling " . $job . "\n"; echo "Cancelling " . $job . "\n";
// throw new Resque_Job_DontPerform; // throw new Resque_Job_DontPerform;
} }
public static function afterPerform($job) public static function afterPerform($job)
@ -49,4 +46,4 @@ class SampleResquePlugin
{ {
echo $job . " threw an exception:\n" . $exception; echo $job . " threw an exception:\n" . $exception;
} }
} }

View file

@ -1,20 +1,18 @@
<?php <?php
namespace Resque;
/** /**
* Base Resque class. * Base Resque class.
* *
* @package Resque * @package Resque
* @author Daniel Mason <daniel@m2.nz> * @author Chris Boulton <chris@bigcommerce.com>
* @license http://www.opensource.org/licenses/mit-license.php * @license http://www.opensource.org/licenses/mit-license.php
*/ */
class Resque class Resque
{ {
public const VERSION = '2.5.3'; const VERSION = '1.4.3';
public const DEFAULT_INTERVAL = 5; const DEFAULT_INTERVAL = 5;
/** /**
* @var Resque_Redis Instance of Resque_Redis that talks to redis. * @var Resque_Redis Instance of Resque_Redis that talks to redis.
@ -52,20 +50,19 @@ class Resque
/** /**
* Return an instance of the Resque_Redis class instantiated for Resque. * Return an instance of the Resque_Redis class instantiated for Resque.
* *
* @return \Resque\Redis Instance of Resque_Redis. * @return Resque_Redis Instance of Resque_Redis.
* * @throws Resque_RedisException
* @throws \Resque\RedisException
*/ */
public static function redis() public static function redis()
{ {
if (!is_null(self::$redis)) { if (self::$redis !== null) {
return self::$redis; return self::$redis;
} }
if (is_callable(self::$redisServer)) { if (is_callable(self::$redisServer)) {
self::$redis = call_user_func(self::$redisServer, self::$redisDatabase); self::$redis = call_user_func(self::$redisServer, self::$redisDatabase);
} else { } else {
self::$redis = new \Resque\Redis(self::$redisServer, self::$redisDatabase); self::$redis = new Resque_Redis(self::$redisServer, self::$redisDatabase);
} }
return self::$redis; return self::$redis;
@ -92,7 +89,7 @@ class Resque
$pid = pcntl_fork(); $pid = pcntl_fork();
if ($pid === -1) { if ($pid === -1) {
throw new \RuntimeException('Unable to fork child worker.'); throw new RuntimeException('Unable to fork child worker.');
} }
return $pid; return $pid;
@ -104,23 +101,19 @@ class Resque
* *
* @param string $queue The name of the queue to add the job to. * @param string $queue The name of the queue to add the job to.
* @param array $item Job description as an array to be JSON encoded. * @param array $item Job description as an array to be JSON encoded.
*
* @return bool * @return bool
*/ */
public static function push($queue, $item): bool public static function push($queue, $item)
{ {
$encodedItem = json_encode($item); $encodedItem = json_encode($item);
if ($encodedItem === false) { if ($encodedItem === false) {
return false; return false;
} }
self::redis()->sadd('queues', $queue); self::redis()->sadd('queues', $queue);
$length = self::redis()->rpush('queue:' . $queue, $encodedItem); $length = self::redis()->rpush('queue:' . $queue, $encodedItem);
if ($length < 1) { if ($length < 1) {
return false; return false;
} }
return true; return true;
} }
@ -129,7 +122,6 @@ class Resque
* return it. * return it.
* *
* @param string $queue The name of the queue to fetch an item from. * @param string $queue The name of the queue to fetch an item from.
*
* @return mixed Decoded item from the queue. * @return mixed Decoded item from the queue.
*/ */
public static function pop($queue) public static function pop($queue)
@ -150,7 +142,7 @@ class Resque
* @param array $items * @param array $items
* @return integer number of deleted items * @return integer number of deleted items
*/ */
public static function dequeue($queue, $items = []) public static function dequeue($queue, $items = Array())
{ {
if (count($items) > 0) { if (count($items) > 0) {
return self::removeItems($queue, $items); return self::removeItems($queue, $items);
@ -163,14 +155,13 @@ class Resque
* Remove specified queue * Remove specified queue
* *
* @param string $queue The name of the queue to remove. * @param string $queue The name of the queue to remove.
* * @return integer Number of deleted items
* @return int Number of deleted items
*/ */
public static function removeQueue($queue): int public static function removeQueue($queue)
{ {
$num = self::removeList($queue); $num = self::removeList($queue);
self::redis()->srem('queues', $queue); self::redis()->srem('queues', $queue);
return intval($num); return $num;
} }
/** /**
@ -179,13 +170,12 @@ class Resque
* *
* @param array $queues * @param array $queues
* @param int $timeout * @param int $timeout
*
* @return array|null|void * @return array|null|void
*/ */
public static function blpop(array $queues, $timeout) public static function blpop(array $queues, $timeout)
{ {
$list = []; $list = array();
foreach ($queues as $queue) { foreach ($queues AS $queue) {
$list[] = 'queue:' . $queue; $list[] = 'queue:' . $queue;
} }
@ -202,10 +192,10 @@ class Resque
*/ */
$queue = substr($item[0], strlen(self::redis()->getPrefix() . 'queue:')); $queue = substr($item[0], strlen(self::redis()->getPrefix() . 'queue:'));
return [ return array(
'queue' => $queue, 'queue' => $queue,
'payload' => json_decode($item[1], true) 'payload' => json_decode($item[1], true)
]; );
} }
/** /**
@ -215,9 +205,9 @@ class Resque
* *
* @return int The size of the queue. * @return int The size of the queue.
*/ */
public static function size($queue): int public static function size($queue)
{ {
return intval(self::redis()->llen('queue:' . $queue)); return self::redis()->llen('queue:' . $queue);
} }
/** /**
@ -233,20 +223,20 @@ class Resque
public static function enqueue($queue, $class, $args = null, $trackStatus = false) public static function enqueue($queue, $class, $args = null, $trackStatus = false)
{ {
$id = Resque::generateJobId(); $id = Resque::generateJobId();
$hookParams = [ $hookParams = array(
'class' => $class, 'class' => $class,
'args' => $args, 'args' => $args,
'queue' => $queue, 'queue' => $queue,
'id' => $id, 'id' => $id,
]; );
try { try {
\Resque\Event::trigger('beforeEnqueue', $hookParams); Resque_Event::trigger('beforeEnqueue', $hookParams);
} catch (\Resque\Job\DontCreate $e) { } catch (Resque_Job_DontCreate $e) {
return false; return false;
} }
\Resque\Job\Job::create($queue, $class, $args, $trackStatus, $id); Resque_Job::create($queue, $class, $args, $trackStatus, $id);
\Resque\Event::trigger('afterEnqueue', $hookParams); Resque_Event::trigger('afterEnqueue', $hookParams);
return $id; return $id;
} }
@ -255,12 +245,11 @@ class Resque
* Reserve and return the next available job in the specified queue. * Reserve and return the next available job in the specified queue.
* *
* @param string $queue Queue to fetch next available job from. * @param string $queue Queue to fetch next available job from.
* * @return false|object|Resque_Job
* @return \Resque\Job\Job|null
*/ */
public static function reserve($queue): ?\Resque\Job\Job public static function reserve($queue)
{ {
return \Resque\Job\Job::reserve($queue); return Resque_Job::reserve($queue);
} }
/** /**
@ -268,10 +257,13 @@ class Resque
* *
* @return array Array of queues. * @return array Array of queues.
*/ */
public static function queues(): array public static function queues()
{ {
$queues = self::redis()->smembers('queues'); $queues = self::redis()->smembers('queues');
return is_array($queues) ? $queues : []; if (!is_array($queues)) {
$queues = array();
}
return $queues;
} }
/** /**
@ -284,10 +276,9 @@ class Resque
* *
* @param string $queue The name of the queue * @param string $queue The name of the queue
* @param array $items * @param array $items
* * @return integer number of deleted items
* @return int number of deleted items
*/ */
private static function removeItems($queue, $items = []): int private static function removeItems($queue, $items = Array())
{ {
$counter = 0; $counter = 0;
$originalQueue = 'queue:' . $queue; $originalQueue = 'queue:' . $queue;
@ -352,11 +343,8 @@ class Resque
# class name with args , example: item[0] = ['class' => {'foo' => 1, 'bar' => 2}] # class name with args , example: item[0] = ['class' => {'foo' => 1, 'bar' => 2}]
} elseif (is_array($val)) { } elseif (is_array($val)) {
$decodedArgs = (array)$decoded['args'][0]; $decodedArgs = (array)$decoded['args'][0];
if ( if ($decoded['class'] == $key &&
$decoded['class'] == $key count($decodedArgs) > 0 && count(array_diff($decodedArgs, $val)) == 0) {
&& count($decodedArgs) > 0
&& count(array_diff($decodedArgs, $val)) == 0
) {
return true; return true;
} }
# class name with ID, example: item[0] = ['class' => 'id'] # class name with ID, example: item[0] = ['class' => 'id']
@ -377,7 +365,7 @@ class Resque
* @params string $queue the name of the queue * @params string $queue the name of the queue
* @param $queue * @param $queue
* @return integer number of deleted items belongs to this list * @return integer number of deleted items belongs to this list
* @throws \Resque\RedisException * @throws Resque_RedisException
*/ */
private static function removeList($queue) private static function removeList($queue)
{ {

View file

@ -1,16 +1,14 @@
<?php <?php
namespace Resque;
/** /**
* Resque event/plugin system class * Resque event/plugin system class
* *
* @package Resque/Event * @package Resque/Event
* @author Daniel Mason <daniel@m2.nz> * @author Chris Boulton <chris@bigcommerce.com>
* @license http://www.opensource.org/licenses/mit-license.php * @license http://www.opensource.org/licenses/mit-license.php
*/ */
class Event class Resque_Event
{ {
/** /**
* @var array Array containing all registered callbacks, indexked by event name. * @var array Array containing all registered callbacks, indexked by event name.
@ -22,7 +20,6 @@ class Event
* *
* @param string $event Name of event to be raised. * @param string $event Name of event to be raised.
* @param mixed $data Optional, any data that should be passed to each callback. * @param mixed $data Optional, any data that should be passed to each callback.
*
* @return true * @return true
*/ */
public static function trigger($event, $data = null) public static function trigger($event, $data = null)
@ -39,8 +36,7 @@ class Event
if (!is_callable($callback)) { if (!is_callable($callback)) {
continue; continue;
} }
call_user_func_array($callback, $data);
call_user_func_array($callback, array_values($data));
} }
return true; return true;
@ -50,8 +46,7 @@ class Event
* Listen in on a given event to have a specified callback fired. * Listen in on a given event to have a specified callback fired.
* *
* @param string $event Name of event to listen on. * @param string $event Name of event to listen on.
* @param mixed $callback Any callback callable by call_user_func_array * @param mixed $callback Any callback callable by call_user_func_array.
*
* @return true * @return true
*/ */
public static function listen($event, $callback) public static function listen($event, $callback)
@ -69,7 +64,6 @@ class Event
* *
* @param string $event Name of event. * @param string $event Name of event.
* @param mixed $callback The callback as defined when listen() was called. * @param mixed $callback The callback as defined when listen() was called.
*
* @return true * @return true
*/ */
public static function stopListening($event, $callback) public static function stopListening($event, $callback)
@ -88,10 +82,8 @@ class Event
/** /**
* Call all registered listeners. * Call all registered listeners.
*
* @return void
*/ */
public static function clearListeners(): void public static function clearListeners()
{ {
self::$events = []; self::$events = [];
} }

View file

@ -1,15 +1,13 @@
<?php <?php
namespace Resque;
/** /**
* Resque exception. * Resque exception.
* *
* @package Resque * @package Resque
* @author Daniel Mason <daniel@m2.nz> * @author Chris Boulton <chris@bigcommerce.com>
* @license http://www.opensource.org/licenses/mit-license.php * @license http://www.opensource.org/licenses/mit-license.php
*/ */
class Exception extends \Exception class Resque_Exception extends Exception
{ {
} }

View file

@ -1,16 +1,14 @@
<?php <?php
namespace Resque\Failure;
/** /**
* Failed Resque job. * Failed Resque job.
* *
* @package Resque/Failure * @package Resque/Failure
* @author Daniel Mason <daniel@m2.nz> * @author Chris Boulton <chris@bigcommerce.com>
* @license http://www.opensource.org/licenses/mit-license.php * @license http://www.opensource.org/licenses/mit-license.php
*/ */
class Failure class Resque_Failure
{ {
/** /**
* @var string Class name representing the backend to pass failed jobs off to. * @var string Class name representing the backend to pass failed jobs off to.
@ -22,15 +20,11 @@ class Failure
* *
* @param array $payload The contents of the job that has just failed. * @param array $payload The contents of the job that has just failed.
* @param \Exception $exception The exception generated when the job failed to run. * @param \Exception $exception The exception generated when the job failed to run.
* @param \Resque\Worker $worker Instance of Resque_Worker that was running this job when it failed. * @param \Resque_Worker $worker Instance of Resque_Worker that was running this job when it failed.
* @param string $queue The name of the queue that this job was fetched from. * @param string $queue The name of the queue that this job was fetched from.
*/ */
public static function create( public static function create($payload, Exception $exception, Resque_Worker $worker, $queue)
$payload, {
\Exception $exception,
\Resque\Worker $worker,
$queue
) {
$backend = self::getBackend(); $backend = self::getBackend();
new $backend($payload, $exception, $worker, $queue); new $backend($payload, $exception, $worker, $queue);
} }
@ -38,12 +32,12 @@ class Failure
/** /**
* Return an instance of the backend for saving job failures. * Return an instance of the backend for saving job failures.
* *
* @return string * @return object|string
*/ */
public static function getBackend() public static function getBackend()
{ {
if (is_null(self::$backend)) { if (self::$backend === null) {
self::$backend = '\\Resque\\Failure\\ResqueFailureRedis'; self::$backend = 'Resque_Failure_Redis';
} }
return self::$backend; return self::$backend;
@ -55,11 +49,9 @@ class Failure
* It is your responsibility to have the backend class loaded (or autoloaded) * It is your responsibility to have the backend class loaded (or autoloaded)
* *
* @param string $backend The class name of the backend to pipe failures to. * @param string $backend The class name of the backend to pipe failures to.
*
* @return void
*/ */
public static function setBackend(string $backend): void public static function setBackend($backend)
{ {
self::$backend = $backend; self::$backend = $backend;
} }
} }

View file

@ -1,15 +1,13 @@
<?php <?php
namespace Resque\Failure;
/** /**
* Interface that all failure backends should implement. * Interface that all failure backends should implement.
* *
* @package Resque\Failure * @package Resque/Failure
* @author Daniel Mason <daniel@m2.nz> * @author Chris Boulton <chris@bigcommerce.com>
* @license http://www.opensource.org/licenses/mit-license.php * @license http://www.opensource.org/licenses/mit-license.php
*/ */
interface ResqueFailureInterface interface Resque_Failure_Interface
{ {
/** /**
* Initialize a failed job class and save it (where appropriate). * Initialize a failed job class and save it (where appropriate).

View file

@ -1,16 +1,13 @@
<?php <?php
namespace Resque\Failure;
/** /**
* Redis backend for storing failed Resque jobs. * Redis backend for storing failed Resque jobs.
* *
* @package Resque\Failure * @package Resque/Failure
* @author Daniel Mason <daniel@m2.nz> * @author Chris Boulton <chris@bigcommerce.com>
* @license http://www.opensource.org/licenses/mit-license.php * @license http://www.opensource.org/licenses/mit-license.php
*/ */
class ResqueFailureRedis implements ResqueFailureInterface class Resque_Failure_Redis implements Resque_Failure_Interface
{ {
/** /**
* Initialize a failed job class and save it (where appropriate). * Initialize a failed job class and save it (where appropriate).
@ -19,12 +16,12 @@ class ResqueFailureRedis implements ResqueFailureInterface
* @param object $exception Instance of the exception that was thrown by the failed job. * @param object $exception Instance of the exception that was thrown by the failed job.
* @param object $worker Instance of Resque_Worker that received the job. * @param object $worker Instance of Resque_Worker that received the job.
* @param string $queue The name of the queue the job was fetched from. * @param string $queue The name of the queue the job was fetched from.
* @throws \Resque\RedisException * @throws Resque_RedisException
*/ */
public function __construct($payload, $exception, $worker, $queue) public function __construct($payload, $exception, $worker, $queue)
{ {
$data = new \stdClass(); $data = new stdClass;
$data->failed_at = date('D M d H:i:s T Y'); $data->failed_at = strftime('%a %b %d %H:%M:%S %Z %Y');
$data->payload = $payload; $data->payload = $payload;
$data->exception = get_class($exception); $data->exception = get_class($exception);
$data->error = $exception->getMessage(); $data->error = $exception->getMessage();
@ -32,6 +29,6 @@ class ResqueFailureRedis implements ResqueFailureInterface
$data->worker = (string)$worker; $data->worker = (string)$worker;
$data->queue = $queue; $data->queue = $queue;
$data = json_encode($data); $data = json_encode($data);
\Resque\Resque::redis()->rpush('failed', $data); Resque::redis()->rpush('failed', $data);
} }
} }

View file

@ -1,16 +1,14 @@
<?php <?php
namespace Resque\Job;
/** /**
* Resque job. * Resque job.
* *
* @package Resque/Job * @package Resque/Job
* @author Daniel Mason <daniel@m2.nz> * @author Chris Boulton <chris@bigcommerce.com>
* @license http://www.opensource.org/licenses/mit-license.php * @license http://www.opensource.org/licenses/mit-license.php
*/ */
class Job class Resque_Job
{ {
/** /**
* @var string The name of the queue that this job belongs to. * @var string The name of the queue that this job belongs to.
@ -18,7 +16,7 @@ class Job
public $queue; public $queue;
/** /**
* @var \Resque\Worker Instance of the Resque worker running this job. * @var Resque_Worker Instance of the Resque worker running this job.
*/ */
public $worker; public $worker;
@ -28,12 +26,12 @@ class Job
public $payload; public $payload;
/** /**
* @var object|\Resque\Job\JobInterface Instance of the class performing work for this job. * @var object|Resque_JobInterface Instance of the class performing work for this job.
*/ */
private $instance; private $instance;
/** /**
* @var \Resque\Job\FactoryInterface * @var Resque_Job_FactoryInterface
*/ */
private $jobFactory; private $jobFactory;
@ -59,21 +57,20 @@ class Job
* @param string $id Unique identifier for tracking the job. Generated if not supplied. * @param string $id Unique identifier for tracking the job. Generated if not supplied.
* *
* @return string * @return string
*
* @throws \InvalidArgumentException * @throws \InvalidArgumentException
*/ */
public static function create($queue, $class, $args = null, $monitor = false, $id = null): string public static function create($queue, $class, $args = null, $monitor = false, $id = null)
{ {
if (is_null($id)) { if (is_null($id)) {
$id = \Resque\Resque::generateJobId(); $id = Resque::generateJobId();
} }
if ($args !== null && !is_array($args)) { if ($args !== null && !is_array($args)) {
throw new \InvalidArgumentException( throw new InvalidArgumentException(
'Supplied $args must be an array.' 'Supplied $args must be an array.'
); );
} }
\Resque\Resque::push($queue, [ Resque::push($queue, [
'class' => $class, 'class' => $class,
'args' => [$args], 'args' => [$args],
'id' => $id, 'id' => $id,
@ -81,7 +78,7 @@ class Job
]); ]);
if ($monitor) { if ($monitor) {
Status::create($id); Resque_Job_Status::create($id);
} }
return $id; return $id;
@ -89,47 +86,43 @@ class Job
/** /**
* Find the next available job from the specified queue and return an * Find the next available job from the specified queue and return an
* instance of \Resque\Job\Job for it. * instance of Resque_Job for it.
* *
* @param string $queue The name of the queue to check for a job in. * @param string $queue The name of the queue to check for a job in.
* * @return false|object Null when there aren't any waiting jobs, instance of Resque_Job when a job was found.
* @return Job|null Null when there aren't any waiting jobs, instance of \Resque\Job\Job when a job was found.
*/ */
public static function reserve($queue): ?Job public static function reserve($queue)
{ {
$payload = \Resque\Resque::pop($queue); $payload = Resque::pop($queue);
if (!is_array($payload)) { if (!is_array($payload)) {
return null; return false;
} }
return new Job($queue, $payload); return new Resque_Job($queue, $payload);
} }
/** /**
* Find the next available job from the specified queues using blocking list pop * Find the next available job from the specified queues using blocking list pop
* and return an instance of \Resque\Job\Job for it. * and return an instance of Resque_Job for it.
* *
* @param array $queues * @param array $queues
* @param int $timeout * @param int $timeout
* * @return false|object Null when there aren't any waiting jobs, instance of Resque_Job when a job was found.
* @return Job|null Null when there aren't any waiting jobs, instance of \Resque\Job\Job when a job was found.
*/ */
public static function reserveBlocking(array $queues, $timeout = null): ?Job public static function reserveBlocking(array $queues, $timeout = null)
{ {
$item = \Resque\Resque::blpop($queues, $timeout); $item = Resque::blpop($queues, $timeout);
if (!is_array($item)) { if (!is_array($item)) {
return null; return false;
} }
return new Job($item['queue'], $item['payload']); return new Resque_Job($item['queue'], $item['payload']);
} }
/** /**
* Update the status of the current job. * Update the status of the current job.
* *
* @param int $status Status constant from \Resque\Job\Status indicating the current status of a job. * @param int $status Status constant from Resque_Job_Status indicating the current status of a job.
*
* @return bool
*/ */
public function updateStatus($status): bool public function updateStatus($status): bool
{ {
@ -137,7 +130,7 @@ class Job
return false; return false;
} }
$statusInstance = new Status($this->payload['id']); $statusInstance = new Resque_Job_Status($this->payload['id']);
$statusInstance->update($status); $statusInstance->update($status);
return true; return true;
} }
@ -145,11 +138,11 @@ class Job
/** /**
* Return the status of the current job. * Return the status of the current job.
* *
* @return int The status of the job as one of the \Resque\Job\Status constants. * @return int The status of the job as one of the Resque_Job_Status constants.
*/ */
public function getStatus() public function getStatus()
{ {
$status = new Status($this->payload['id']); $status = new Resque_Job_Status($this->payload['id']);
return $status->get(); return $status->get();
} }
@ -169,12 +162,11 @@ class Job
/** /**
* Get the instantiated object for this job that will be performing work. * Get the instantiated object for this job that will be performing work.
* * @return Resque_JobInterface Instance of the object that this job belongs to.
* @return \Resque\Job\JobInterface Instance of the object that this job belongs to.
*/ */
public function getInstance() public function getInstance()
{ {
if (isset($this->instance) && !is_null($this->instance)) { if (!is_null($this->instance)) {
return $this->instance; return $this->instance;
} }
@ -188,13 +180,12 @@ class Job
* associated with the job with the supplied arguments. * associated with the job with the supplied arguments.
* *
* @return bool * @return bool
* * @throws Resque_Exception When the job's class could not be found or it does not contain a perform method.
* @throws \Resque\Exception When the job's class could not be found or it does not contain a perform method.
*/ */
public function perform() public function perform()
{ {
try { try {
\Resque\Event::trigger('beforePerform', $this); Resque_Event::trigger('beforePerform', $this);
$instance = $this->getInstance(); $instance = $this->getInstance();
if (method_exists($instance, 'setUp')) { if (method_exists($instance, 'setUp')) {
@ -207,9 +198,9 @@ class Job
$instance->tearDown(); $instance->tearDown();
} }
\Resque\Event::trigger('afterPerform', $this); Resque_Event::trigger('afterPerform', $this);
} catch (DontPerform $e) { } // beforePerform/setUp have said don't perform this job. Return.
/** @noinspection PhpRedundantCatchClauseInspection */ /** @noinspection PhpRedundantCatchClauseInspection */ catch (Resque_Job_DontPerform $e) {
return false; return false;
} }
@ -223,30 +214,29 @@ class Job
*/ */
public function fail($exception) public function fail($exception)
{ {
\Resque\Event::trigger('onFailure', [ Resque_Event::trigger('onFailure', [
'exception' => $exception, 'exception' => $exception,
'job' => $this, 'job' => $this,
]); ]);
$this->updateStatus(Status::STATUS_FAILED); $this->updateStatus(Resque_Job_Status::STATUS_FAILED);
\Resque\Failure\Failure::create( Resque_Failure::create(
$this->payload, $this->payload,
$exception, $exception,
$this->worker, $this->worker,
$this->queue $this->queue
); );
\Resque\Stat::incr('failed'); Resque_Stat::incr('failed');
\Resque\Stat::incr('failed:' . $this->worker); Resque_Stat::incr('failed:' . $this->worker);
} }
/** /**
* Re-queue the current job. * Re-queue the current job.
*
* @return string * @return string
*/ */
public function recreate() public function recreate()
{ {
$status = new Status($this->payload['id']); $status = new Resque_Job_Status($this->payload['id']);
$monitor = false; $monitor = false;
if ($status->isTracking()) { if ($status->isTracking()) {
$monitor = true; $monitor = true;
@ -276,11 +266,10 @@ class Job
} }
/** /**
* @param FactoryInterface $jobFactory * @param Resque_Job_FactoryInterface $jobFactory
* * @return Resque_Job
* @return Job
*/ */
public function setJobFactory(FactoryInterface $jobFactory) public function setJobFactory(Resque_Job_FactoryInterface $jobFactory)
{ {
$this->jobFactory = $jobFactory; $this->jobFactory = $jobFactory;
@ -288,14 +277,13 @@ class Job
} }
/** /**
* @return FactoryInterface * @return Resque_Job_FactoryInterface
*/ */
public function getJobFactory() public function getJobFactory()
{ {
if (is_null($this->jobFactory)) { if ($this->jobFactory === null) {
$this->jobFactory = new Factory(); $this->jobFactory = new Resque_Job_Factory();
} }
return $this->jobFactory; return $this->jobFactory;
} }
} }

View file

@ -1,14 +1,13 @@
<?php <?php
namespace Resque\Job;
/** /**
* Runtime exception class for a job that does not exit cleanly. * Runtime exception class for a job that does not exit cleanly.
* *
* @package Resque/Job * @package Resque/Job
* @author Daniel Mason <daniel@m2.nz> * @author Chris Boulton <chris@bigcommerce.com>
* @license http://www.opensource.org/licenses/mit-license.php * @license http://www.opensource.org/licenses/mit-license.php
*/ */
class DirtyExitException extends \RuntimeException class Resque_Job_DirtyExitException extends RuntimeException
{ {
} }

View file

@ -1,14 +1,13 @@
<?php <?php
namespace Resque\Job;
/** /**
* Exception to be thrown if while enqueuing a job it should not be created. * Exception to be thrown if while enqueuing a job it should not be created.
* *
* @package Resque/Job * @package Resque/Job
* @author Daniel Mason <daniel@m2.nz> * @author Chris Boulton <chris@bigcommerce.com>
* @license http://www.opensource.org/licenses/mit-license.php * @license http://www.opensource.org/licenses/mit-license.php
*/ */
class DontCreate extends \Exception class Resque_Job_DontCreate extends Exception
{ {
} }

View file

@ -1,14 +1,14 @@
<?php <?php
namespace Resque\Job;
/** /**
* Exception to be thrown if a job should not be performed/run. * Exception to be thrown if a job should not be performed/run.
* *
* @package Resque/Job * @package Resque/Job
* @author Daniel Mason <daniel@m2.nz> * @author Chris Boulton <chris@bigcommerce.com>
* @license http://www.opensource.org/licenses/mit-license.php * @license http://www.opensource.org/licenses/mit-license.php
*/ */
class DontPerform extends \Exception
class Resque_Job_DontPerform extends Exception
{ {
} }

View file

@ -0,0 +1,32 @@
<?php
class Resque_Job_Factory implements Resque_Job_FactoryInterface
{
/**
* @param $className
* @param array $args
* @param $queue
* @return Resque_JobInterface
* @throws \Resque_Exception
*/
public function create($className, $args, $queue)
{
if (!class_exists($className)) {
throw new Resque_Exception(
'Could not find job class ' . $className . '.'
);
}
if (!method_exists($className, 'perform')) {
throw new Resque_Exception(
'Job class ' . $className . ' does not contain a perform method.'
);
}
$instance = new $className;
$instance->args = $args;
$instance->queue = $queue;
return $instance;
}
}

View file

@ -0,0 +1,12 @@
<?php
interface Resque_Job_FactoryInterface
{
/**
* @param $className
* @param array $args
* @param $queue
* @return Resque_JobInterface
*/
public function create($className, $args, $queue);
}

View file

@ -1,21 +1,19 @@
<?php <?php
namespace Resque\Job;
/** /**
* Status tracker/information for a job. * Status tracker/information for a job.
* *
* @package Resque/Job * @package Resque/Job
* @author Daniel Mason <daniel@m2.nz> * @author Chris Boulton <chris@bigcommerce.com>
* @license http://www.opensource.org/licenses/mit-license.php * @license http://www.opensource.org/licenses/mit-license.php
*/ */
class Status class Resque_Job_Status
{ {
public const STATUS_WAITING = 1; const STATUS_WAITING = 1;
public const STATUS_RUNNING = 2; const STATUS_RUNNING = 2;
public const STATUS_FAILED = 3; const STATUS_FAILED = 3;
public const STATUS_COMPLETE = 4; const STATUS_COMPLETE = 4;
/** /**
* @var string The ID of the job this status class refers back to. * @var string The ID of the job this status class refers back to.
@ -59,11 +57,7 @@ class Status
'updated' => time(), 'updated' => time(),
'started' => time(), 'started' => time(),
]; ];
\Resque\Resque::redis()->set( Resque::redis()->set('job:' . $id . ':status', json_encode($statusPacket));
'job:' . $id . ':status',
json_encode($statusPacket),
['ex' => \Resque\Redis::DEFAULT_REDIS_TTL],
);
} }
/** /**
@ -78,7 +72,7 @@ class Status
return false; return false;
} }
if (!\Resque\Resque::redis()->exists((string)$this)) { if (!Resque::redis()->exists((string)$this)) {
$this->isTracking = false; $this->isTracking = false;
return false; return false;
} }
@ -90,7 +84,7 @@ class Status
/** /**
* Update the status indicator for the current job with a new status. * Update the status indicator for the current job with a new status.
* *
* @param int The status of the job (see constants in \Resque\Job\Status) * @param int The status of the job (see constants in Resque_Job_Status)
*/ */
public function update($status) public function update($status)
{ {
@ -102,19 +96,19 @@ class Status
'status' => $status, 'status' => $status,
'updated' => time(), 'updated' => time(),
]; ];
Resque::redis()->set((string)$this, json_encode($statusPacket));
\Resque\Resque::redis()->set( // Expire the status for completed jobs after 24 hours
(string)$this, if (in_array($status, self::$completeStatuses)) {
json_encode($statusPacket), Resque::redis()->expire((string)$this, 86400);
['ex' => \Resque\Redis::DEFAULT_REDIS_TTL], }
);
} }
/** /**
* Fetch the status for the job being monitored. * Fetch the status for the job being monitored.
* *
* @return mixed False if the status is not being monitored, otherwise the status as * @return mixed False if the status is not being monitored, otherwise the status as
* as an integer, based on the \Resque\Job\Status constants. * as an integer, based on the Resque_Job_Status constants.
*/ */
public function get() public function get()
{ {
@ -122,7 +116,7 @@ class Status
return false; return false;
} }
$statusPacket = json_decode(\Resque\Resque::redis()->get((string)$this), true); $statusPacket = json_decode(Resque::redis()->get((string)$this), true);
if (!$statusPacket) { if (!$statusPacket) {
return false; return false;
} }
@ -132,12 +126,10 @@ class Status
/** /**
* Stop tracking the status of a job. * Stop tracking the status of a job.
*
* @return void
*/ */
public function stop(): void public function stop()
{ {
\Resque\Resque::redis()->del((string)$this); Resque::redis()->del((string)$this);
} }
/** /**

View file

@ -1,8 +1,6 @@
<?php <?php
namespace Resque\Job; interface Resque_JobInterface
interface JobInterface
{ {
/** /**
* @return bool * @return bool

View file

@ -1,20 +1,18 @@
<?php <?php
namespace Resque;
/** /**
* Resque default logger PSR-3 compliant * Resque default logger PSR-3 compliant
* *
* @package Resque * @package Resque/Stat
* @author Daniel Mason <daniel@m2.nz> * @author Chris Boulton <chris@bigcommerce.com>
* @license http://www.opensource.org/licenses/mit-license.php * @license http://www.opensource.org/licenses/mit-license.php
*/ */
class Log extends \Psr\Log\AbstractLogger class Resque_Log extends Psr\Log\AbstractLogger
{ {
public $logLevel; public $logLevel;
public function __construct($logLevel = 'warning') public function __construct($logLevel = "warning")
{ {
$this->logLevel = strtolower($logLevel); $this->logLevel = strtolower($logLevel);
} }
@ -25,22 +23,21 @@ class Log extends \Psr\Log\AbstractLogger
* @param mixed $level PSR-3 log level constant, or equivalent string * @param mixed $level PSR-3 log level constant, or equivalent string
* @param string $message Message to log, may contain a { placeholder } * @param string $message Message to log, may contain a { placeholder }
* @param array $context Variables to replace { placeholder } * @param array $context Variables to replace { placeholder }
*
* @return null * @return null
*/ */
public function log($level, $message, array $context = []): void public function log($level, $message, array $context = [])
{ {
$logLevels = [ $logLevels = [
'emergency', "emergency",
'alert', "alert",
'critical', "critical",
'error', "error",
'warning', "warning",
'notice', "notice",
'info', "info",
'debug', "debug"
]; ];
/** /**
* Only log things with a higher level than the current log level. * Only log things with a higher level than the current log level.
* e.g If set as 'alert' will only alert for 'emergency' and 'alert' logs. * e.g If set as 'alert' will only alert for 'emergency' and 'alert' logs.
@ -48,11 +45,11 @@ class Log extends \Psr\Log\AbstractLogger
if (array_search($level, $logLevels) <= array_search($this->logLevel, $logLevels)) { if (array_search($level, $logLevels) <= array_search($this->logLevel, $logLevels)) {
fwrite( fwrite(
STDOUT, STDOUT,
'[' . $level . '][' . date('Y-m-d H:i:s') . '] ' . '[' . $level . '][' . strftime('%Y-%m-%d %T') . '] ' . $this->interpolate($message, $context) . PHP_EOL
$this->interpolate($message, $context) . PHP_EOL
); );
} }
return; return;
} }
/** /**

View file

@ -1,27 +1,23 @@
<?php <?php
namespace Resque;
/** /**
* Set up phpredis connection * Set up phpredis connection
* *
* @package Resque/Redis * @package Resque/Redis
* @author Daniel Mason <daniel@m2.nz> * @author Chris Boulton <chris@bigcommerce.com>
* @license http://www.opensource.org/licenses/mit-license.php * @license http://www.opensource.org/licenses/mit-license.php
*/ */
class Redis class Resque_Redis
{ {
/** /**
* Redis Client * Redis Client
* * @var Credis_Client
* @var \Credis_Client
*/ */
private $driver; private $driver;
/** /**
* Redis namespace * Redis namespace
*
* @var string * @var string
*/ */
private static $defaultNamespace = 'resque:'; private static $defaultNamespace = 'resque:';
@ -29,22 +25,17 @@ class Redis
/** /**
* A default host to connect to * A default host to connect to
*/ */
public const DEFAULT_HOST = 'localhost'; const DEFAULT_HOST = 'localhost';
/** /**
* The default Redis port * The default Redis port
*/ */
public const DEFAULT_PORT = 6379; const DEFAULT_PORT = 6379;
/** /**
* The default Redis Database number * The default Redis Database number
*/ */
public const DEFAULT_DATABASE = 0; const DEFAULT_DATABASE = 0;
/**
* Default Redis TTL (2 days)
*/
public const DEFAULT_REDIS_TTL = 172800;
/** /**
* @var array List of all commands in Redis that supply a key as their * @var array List of all commands in Redis that supply a key as their
@ -97,20 +88,27 @@ class Redis
'rename', 'rename',
'rpoplpush' 'rpoplpush'
]; ];
// sinterstore
// sunion
// sunionstore
// sdiff
// sdiffstore
// sinter
// smove
// mget
// msetnx
// mset
// renamenx
/** /**
* Set Redis namespace (prefix) default: resque * Set Redis namespace (prefix) default: resque
*
* @param string $namespace * @param string $namespace
*
* @return void
*/ */
public static function prefix(string $namespace): void public static function prefix($namespace)
{ {
if (substr($namespace, -1) !== ':' && $namespace != '') { if (substr($namespace, -1) !== ':' && $namespace != '') {
$namespace .= ':'; $namespace .= ':';
} }
self::$defaultNamespace = $namespace; self::$defaultNamespace = $namespace;
} }
@ -118,9 +116,8 @@ class Redis
* @param string|array $server A DSN or array * @param string|array $server A DSN or array
* @param int $database A database number to select. However, if we find a valid database number in the DSN the * @param int $database A database number to select. However, if we find a valid database number in the DSN the
* DSN-supplied value will be used instead and this parameter is ignored. * DSN-supplied value will be used instead and this parameter is ignored.
* @param object $client Optional \Credis_Client instance instantiated by you * @param object $client Optional Credis_Client instance instantiated by you
* * @throws Resque_RedisException
* @throws \Resque\RedisException
*/ */
public function __construct($server, $database = null, $client = null) public function __construct($server, $database = null, $client = null)
{ {
@ -134,7 +131,7 @@ class Redis
$timeout = isset($options['timeout']) ? intval($options['timeout']) : null; $timeout = isset($options['timeout']) ? intval($options['timeout']) : null;
$persistent = isset($options['persistent']) ? $options['persistent'] : ''; $persistent = isset($options['persistent']) ? $options['persistent'] : '';
$maxRetries = isset($options['max_connect_retries']) ? $options['max_connect_retries'] : 0; $maxRetries = isset($options['max_connect_retries']) ? $options['max_connect_retries'] : 0;
$this->driver = new \Credis_Client($host, $port, $timeout, $persistent); $this->driver = new Credis_Client($host, $port, $timeout, $persistent);
$this->driver->setMaxConnectRetries($maxRetries); $this->driver->setMaxConnectRetries($maxRetries);
if ($password) { if ($password) {
$this->driver->auth($password); $this->driver->auth($password);
@ -148,8 +145,8 @@ class Redis
if ($database !== null) { if ($database !== null) {
$this->driver->select($database); $this->driver->select($database);
} }
} catch (\Exception $e) { } catch (Exception $e) {
throw new RedisException('Error communicating with Redis: ' . $e->getMessage(), 0, $e); throw new Resque_RedisException('Error communicating with Redis: ' . $e->getMessage(), 0, $e);
} }
} }
@ -164,11 +161,10 @@ class Redis
* Note: the 'user' part of the DSN is not used. * Note: the 'user' part of the DSN is not used.
* *
* @param string $dsn A DSN string * @param string $dsn A DSN string
*
* @return array An array of DSN compotnents, with 'false' values for any unknown components. e.g. * @return array An array of DSN compotnents, with 'false' values for any unknown components. e.g.
* [host, port, db, user, pass, options] * [host, port, db, user, pass, options]
*/ */
public static function parseDsn($dsn): array public static function parseDsn($dsn)
{ {
if ($dsn == '') { if ($dsn == '') {
// Use a sensible default for an empty DNS string // Use a sensible default for an empty DNS string
@ -235,16 +231,14 @@ class Redis
* *
* @param string $name The name of the method called. * @param string $name The name of the method called.
* @param array $args Array of supplied arguments to the method. * @param array $args Array of supplied arguments to the method.
*
* @return mixed Return value from Resident::call() based on the command. * @return mixed Return value from Resident::call() based on the command.
*
* @throws Resque_RedisException * @throws Resque_RedisException
*/ */
public function __call($name, $args) public function __call($name, $args)
{ {
if (in_array($name, $this->keyCommands)) { if (in_array($name, $this->keyCommands)) {
if (is_array($args[0])) { if (is_array($args[0])) {
foreach ($args[0] as $i => $v) { foreach ($args[0] AS $i => $v) {
$args[0][$i] = self::$defaultNamespace . $v; $args[0][$i] = self::$defaultNamespace . $v;
} }
} else { } else {
@ -253,18 +247,23 @@ class Redis
} }
try { try {
return $this->driver->__call($name, $args); return $this->driver->__call($name, $args);
} catch (\Exception $e) { } catch (CredisException $e) {
throw new RedisException('Error communicating with Redis: ' . $e->getMessage(), 0, $e); throw new Resque_RedisException('Error communicating with Redis: ' . $e->getMessage(), 0, $e);
} }
} }
/**
* Returns redis prefix
*
* @return string
*/
public static function getPrefix(): string public static function getPrefix(): string
{ {
return self::$defaultNamespace; return self::$defaultNamespace;
} }
public static function removePrefix($string): string
{
$prefix = self::getPrefix();
if (substr($string, 0, strlen($prefix)) == $prefix) {
$string = substr($string, strlen($prefix), strlen($string));
}
return $string;
}
} }

View file

@ -0,0 +1,14 @@
<?php
/**
* Redis related exceptions
*
* @package Resque
* @author Chris Boulton <chris@bigcommerce.com>
* @license http://www.opensource.org/licenses/mit-license.php
*/
class Resque_RedisException extends Resque_Exception
{
}

View file

@ -1,25 +1,22 @@
<?php <?php
namespace Resque;
/** /**
* Resque statistic management (jobs processed, failed, etc) * Resque statistic management (jobs processed, failed, etc)
* *
* @package Resque * @package Resque/Stat
* @author Daniel Mason <daniel@m2.nz> * @author Chris Boulton <chris@bigcommerce.com>
* @license http://www.opensource.org/licenses/mit-license.php * @license http://www.opensource.org/licenses/mit-license.php
*/ */
class Stat class Resque_Stat
{ {
/** /**
* Get the value of the supplied statistic counter for the specified statistic. * Get the value of the supplied statistic counter for the specified statistic.
* *
* @param string $stat The name of the statistic to get the stats for. * @param string $stat The name of the statistic to get the stats for.
* * @return mixed Value of the statistic.
* @return int Value of the statistic.
*/ */
public static function get(string $stat): int public static function get($stat): int
{ {
return (int)Resque::redis()->get('stat:' . $stat); return (int)Resque::redis()->get('stat:' . $stat);
} }
@ -29,24 +26,11 @@ class Stat
* *
* @param string $stat The name of the statistic to increment. * @param string $stat The name of the statistic to increment.
* @param int $by The amount to increment the statistic by. * @param int $by The amount to increment the statistic by.
* * @return boolean True if successful, false if not.
* @return bool True if successful, false if not.
*/ */
public static function incr(string $stat, int $by = 1): bool public static function incr($stat, $by = 1): bool
{ {
// Make sure we set a TTL by default return (bool)Resque::redis()->incrby('stat:' . $stat, $by);
$set = Resque::redis()->set(
'stat:' . $stat,
$by,
['ex' => Redis::DEFAULT_REDIS_TTL, 'nx'],
);
// If it already exists, return the incrby value
if (!$set) {
return (bool)Resque::redis()->incrby('stat:' . $stat, $by);
}
return true;
} }
/** /**
@ -54,10 +38,9 @@ class Stat
* *
* @param string $stat The name of the statistic to decrement. * @param string $stat The name of the statistic to decrement.
* @param int $by The amount to decrement the statistic by. * @param int $by The amount to decrement the statistic by.
* * @return boolean True if successful, false if not.
* @return bool True if successful, false if not.
*/ */
public static function decr(string $stat, int $by = 1): bool public static function decr($stat, $by = 1): bool
{ {
return (bool)Resque::redis()->decrby('stat:' . $stat, $by); return (bool)Resque::redis()->decrby('stat:' . $stat, $by);
} }
@ -66,11 +49,10 @@ class Stat
* Delete a statistic with the given name. * Delete a statistic with the given name.
* *
* @param string $stat The name of the statistic to delete. * @param string $stat The name of the statistic to delete.
* * @return boolean True if successful, false if not.
* @return bool True if successful, false if not.
*/ */
public static function clear(string $stat): bool public static function clear($stat): bool
{ {
return (bool)Resque::redis()->del('stat:' . $stat); return (bool)Resque::redis()->del('stat:' . $stat);
} }
} }

View file

@ -1,20 +1,17 @@
<?php <?php
declare(ticks=1); declare(ticks=1);
namespace Resque;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
/** /**
* Resque worker that handles checking queues for jobs, fetching them * Resque worker that handles checking queues for jobs, fetching them
* off the queues, running them and handling the result. * off the queues, running them and handling the result.
* *
* @package Resque * @package Resque/Worker
* @author Daniel Mason <daniel@m2.nz> * @author Chris Boulton <chris@bigcommerce.com>
* @license http://www.opensource.org/licenses/mit-license.php * @license http://www.opensource.org/licenses/mit-license.php
*/ */
class Worker class Resque_Worker
{ {
/** /**
* @var LoggerInterface Logging object that impliments the PSR-3 LoggerInterface * @var LoggerInterface Logging object that impliments the PSR-3 LoggerInterface
@ -47,7 +44,7 @@ class Worker
private $id; private $id;
/** /**
* @var \Resque\Job\Job Current job, if any, being processed by this worker. * @var Resque_Job Current job, if any, being processed by this worker.
*/ */
private $currentJob = null; private $currentJob = null;
@ -69,7 +66,7 @@ class Worker
*/ */
public function __construct($queues) public function __construct($queues)
{ {
$this->logger = new Log(); $this->logger = new Resque_Log();
if (!is_array($queues)) { if (!is_array($queues)) {
$queues = [$queues]; $queues = [$queues];
@ -83,7 +80,6 @@ class Worker
/** /**
* Return all workers known to Resque as instantiated instances. * Return all workers known to Resque as instantiated instances.
*
* @return array * @return array
*/ */
public static function all(): array public static function all(): array
@ -97,17 +93,14 @@ class Worker
foreach ($workers as $workerId) { foreach ($workers as $workerId) {
$instances[] = self::find($workerId); $instances[] = self::find($workerId);
} }
return $instances; return $instances;
} }
/** /**
* Given a worker ID, check if it is registered/valid. * Given a worker ID, check if it is registered/valid.
* *
* @param string $workerId ID of the worker * @param string $workerId ID of the worker.
* * @return boolean True if the worker exists, false if not.
* @return boolean True if the worker exists, false if not
*
* @throws Resque_RedisException * @throws Resque_RedisException
*/ */
public static function exists($workerId): bool public static function exists($workerId): bool
@ -118,24 +111,20 @@ class Worker
/** /**
* Given a worker ID, find it and return an instantiated worker class for it. * Given a worker ID, find it and return an instantiated worker class for it.
* *
* @param string $workerId The ID of the worker * @param string $workerId The ID of the worker.
* * @return bool|Resque_Worker
* @return Resque_Worker|bool
*
* @throws Resque_RedisException * @throws Resque_RedisException
*/ */
public static function find($workerId) public static function find($workerId)
{ {
if (false === strpos($workerId, ":") || !self::exists($workerId)) { if (!self::exists($workerId) || false === strpos($workerId, ":")) {
return false; return false;
} }
/** @noinspection PhpUnusedLocalVariableInspection */ /** @noinspection PhpUnusedLocalVariableInspection */
list($hostname, $pid, $queues) = explode(':', $workerId, 3); list($hostname, $pid, $queues) = explode(':', $workerId, 3);
$queues = explode(',', $queues); $queues = explode(',', $queues);
$worker = new self($queues); $worker = new self($queues);
$worker->setId($workerId); $worker->setId($workerId);
return $worker; return $worker;
} }
@ -143,10 +132,8 @@ class Worker
* Set the ID of this worker to a given ID string. * Set the ID of this worker to a given ID string.
* *
* @param string $workerId ID for the worker. * @param string $workerId ID for the worker.
*
* @return void
*/ */
public function setId($workerId): void public function setId($workerId)
{ {
$this->id = $workerId; $this->id = $workerId;
} }
@ -159,12 +146,9 @@ class Worker
* *
* @param int $interval How often to check for new jobs across the queues. * @param int $interval How often to check for new jobs across the queues.
* @param bool $blocking * @param bool $blocking
*
* @return void
*
* @throws Resque_RedisException * @throws Resque_RedisException
*/ */
public function work($interval = Resque::DEFAULT_INTERVAL, $blocking = false): void public function work($interval = Resque::DEFAULT_INTERVAL, $blocking = false)
{ {
$this->updateProcLine('Starting'); $this->updateProcLine('Starting');
$this->startup(); $this->startup();
@ -178,14 +162,8 @@ class Worker
$job = false; $job = false;
if (!$this->paused) { if (!$this->paused) {
if ($blocking === true) { if ($blocking === true) {
$this->logger->log( $this->logger->log(Psr\Log\LogLevel::INFO, 'Starting blocking with timeout of {interval}', ['interval' => $interval]);
\Psr\Log\LogLevel::INFO, $this->updateProcLine('Waiting for ' . implode(',', $this->queues) . ' with blocking timeout ' . $interval);
'Starting blocking with timeout of {interval}',
['interval' => $interval],
);
$this->updateProcLine(
'Waiting for ' . implode(',', $this->queues) . ' with blocking timeout ' . $interval
);
} else { } else {
$this->updateProcLine('Waiting for ' . implode(',', $this->queues) . ' with interval ' . $interval); $this->updateProcLine('Waiting for ' . implode(',', $this->queues) . ' with interval ' . $interval);
} }
@ -201,12 +179,7 @@ class Worker
if ($blocking === false) { if ($blocking === false) {
// If no job was found, we sleep for $interval before continuing and checking again // If no job was found, we sleep for $interval before continuing and checking again
$this->logger->log( $this->logger->log(Psr\Log\LogLevel::INFO, 'Sleeping for {interval}', ['interval' => $interval]);
\Psr\Log\LogLevel::INFO,
'Sleeping for {interval}',
['interval' => $interval],
);
if ($this->paused) { if ($this->paused) {
$this->updateProcLine('Paused'); $this->updateProcLine('Paused');
} else { } else {
@ -219,19 +192,17 @@ class Worker
continue; continue;
} }
$this->logger->log(\Psr\Log\LogLevel::NOTICE, 'Starting work on {job}', ['job' => $job]); $this->logger->log(Psr\Log\LogLevel::NOTICE, 'Starting work on {job}', ['job' => $job]);
Event::trigger('beforeFork', $job); Resque_Event::trigger('beforeFork', $job);
$this->workingOn($job); $this->workingOn($job);
$this->child = Resque::fork(); $this->child = Resque::fork();
// Forked and we're the child. Run the job. // Forked and we're the child. Run the job.
if ($this->child === 0 || $this->child === false) { if ($this->child === 0 || $this->child === false) {
$status = 'Processing ' . $job->queue $status = 'Processing ' . $job->queue . ' since ' . strftime('%F %T');
. ' (' . ($job->payload['class'] ?? '') . ') since '
. date('Y-m-d H:i:s');
$this->updateProcLine($status); $this->updateProcLine($status);
$this->logger->log(\Psr\Log\LogLevel::INFO, $status); $this->logger->log(Psr\Log\LogLevel::INFO, $status);
/** @noinspection PhpParamsInspection */ /** @noinspection PhpParamsInspection */
$this->perform($job); $this->perform($job);
if ($this->child === 0) { if ($this->child === 0) {
@ -241,15 +212,15 @@ class Worker
if ($this->child > 0) { if ($this->child > 0) {
// Parent process, sit and wait // Parent process, sit and wait
$status = 'Forked ' . $this->child . ' at ' . date('Y-m-d H:i:s'); $status = 'Forked ' . $this->child . ' at ' . strftime('%F %T');
$this->updateProcLine($status); $this->updateProcLine($status);
$this->logger->log(\Psr\Log\LogLevel::INFO, $status); $this->logger->log(Psr\Log\LogLevel::INFO, $status);
// Wait until the child process finishes before continuing // Wait until the child process finishes before continuing
pcntl_wait($status); pcntl_wait($status);
$exitStatus = pcntl_wexitstatus($status); $exitStatus = pcntl_wexitstatus($status);
if ($exitStatus !== 0) { if ($exitStatus !== 0) {
$job->fail(new \Resque\Job\DirtyExitException( $job->fail(new Resque_Job_DirtyExitException(
'Job exited with exit code ' . $exitStatus 'Job exited with exit code ' . $exitStatus
)); ));
} }
@ -263,32 +234,29 @@ class Worker
} }
/** /**
* Process a single job * Process a single job.
* *
* @param \Resque\Job\Job $job The job to be processed * @param Resque_Job $job The job to be processed.
*
* @return void
*/ */
public function perform(\Resque\Job\Job $job): void public function perform(Resque_Job $job)
{ {
try { try {
Event::trigger('afterFork', $job); Resque_Event::trigger('afterFork', $job);
$job->perform(); $job->perform();
} catch (\Exception $e) { } catch (Exception $e) {
$this->logger->log(\Psr\Log\LogLevel::CRITICAL, '{job} has failed {stack}', ['job' => $job, 'stack' => $e]); $this->logger->log(Psr\Log\LogLevel::CRITICAL, '{job} has failed {stack}', ['job' => $job, 'stack' => $e]);
$job->fail($e); $job->fail($e);
return; return;
} }
$job->updateStatus(\Resque\Job\Status::STATUS_COMPLETE); $job->updateStatus(Resque_Job_Status::STATUS_COMPLETE);
$this->logger->log(\Psr\Log\LogLevel::NOTICE, '{job} has finished', ['job' => $job]); $this->logger->log(Psr\Log\LogLevel::NOTICE, '{job} has finished', ['job' => $job]);
} }
/** /**
* @param bool $blocking * @param bool $blocking
* @param int $timeout * @param int $timeout
* * @return object|boolean Instance of Resque_Job if a job is found, false if not.
* @return object|boolean - Instance of \Resque\Job\Job if a job is found, false if not
*/ */
public function reserve($blocking = false, $timeout = null) public function reserve($blocking = false, $timeout = null)
{ {
@ -298,17 +266,17 @@ class Worker
} }
if ($blocking === true) { if ($blocking === true) {
$job = \Resque\Job\Job::reserveBlocking($queues, $timeout); $job = Resque_Job::reserveBlocking($queues, $timeout);
if (!is_null($job)) { if ($job) {
$this->logger->log(\Psr\Log\LogLevel::INFO, 'Found job on {queue}', ['queue' => $job->queue]); $this->logger->log(Psr\Log\LogLevel::INFO, 'Found job on {queue}', ['queue' => $job->queue]);
return $job; return $job;
} }
} else { } else {
foreach ($queues as $queue) { foreach ($queues as $queue) {
$this->logger->log(\Psr\Log\LogLevel::INFO, 'Checking {queue} for jobs', ['queue' => $queue]); $this->logger->log(Psr\Log\LogLevel::INFO, 'Checking {queue} for jobs', ['queue' => $queue]);
$job = \Resque\Job\Job::reserve($queue); $job = Resque_Job::reserve($queue);
if (!is_null($job)) { if ($job) {
$this->logger->log(\Psr\Log\LogLevel::INFO, 'Found job on {queue}', ['queue' => $job->queue]); $this->logger->log(Psr\Log\LogLevel::INFO, 'Found job on {queue}', ['queue' => $job->queue]);
return $job; return $job;
} }
} }
@ -319,17 +287,16 @@ class Worker
/** /**
* Return an array containing all of the queues that this worker should use * Return an array containing all of the queues that this worker should use
* when searching for jobs * when searching for jobs.
* *
* If * is found in the list of queues, every queue will be searched in * If * is found in the list of queues, every queue will be searched in
* alphabetic order. (@param boolean $fetch If true, and the queue is set to *, will fetch * alphabetic order. (@see $fetch)
* all queue names from redis
* *
* @param boolean $fetch * @param boolean $fetch If true, and the queue is set to *, will fetch
* * all queue names from redis.
* @return array Array of associated queues * @return array Array of associated queues.
*/ */
public function queues(bool $fetch = true): array public function queues($fetch = true)
{ {
if (!in_array('*', $this->queues) || $fetch == false) { if (!in_array('*', $this->queues) || $fetch == false) {
return $this->queues; return $this->queues;
@ -337,20 +304,17 @@ class Worker
$queues = Resque::queues(); $queues = Resque::queues();
sort($queues); sort($queues);
return $queues; return $queues;
} }
/** /**
* Perform necessary actions to start a worker * Perform necessary actions to start a worker.
*
* @return void
*/ */
private function startup(): void private function startup()
{ {
$this->registerSigHandlers(); $this->registerSigHandlers();
$this->pruneDeadWorkers(); $this->pruneDeadWorkers();
Event::trigger('beforeFirstFork', $this); Resque_Event::trigger('beforeFirstFork', $this);
$this->registerWorker(); $this->registerWorker();
} }
@ -359,16 +323,14 @@ class Worker
* the name of the currently running process to indicate the current state * the name of the currently running process to indicate the current state
* of a worker. * of a worker.
* *
* @param string $status The updated process title * @param string $status The updated process title.
*
* @return void
*/ */
private function updateProcLine($status): void private function updateProcLine($status)
{ {
$processTitle = 'resque-' . Resque::VERSION . ': ' . $status; $processTitle = 'resque-' . Resque::VERSION . ': ' . $status;
if (function_exists('cli_set_process_title') && PHP_OS !== 'Darwin') { if (function_exists('cli_set_process_title') && PHP_OS !== 'Darwin') {
cli_set_process_title($processTitle); cli_set_process_title($processTitle);
} elseif (function_exists('setproctitle')) { } else if (function_exists('setproctitle')) {
setproctitle($processTitle); setproctitle($processTitle);
} }
} }
@ -380,10 +342,8 @@ class Worker
* INT: Shutdown immediately and stop processing jobs. * INT: Shutdown immediately and stop processing jobs.
* QUIT: Shutdown after the current job finishes processing. * QUIT: Shutdown after the current job finishes processing.
* USR1: Kill the forked child immediately and continue processing jobs. * USR1: Kill the forked child immediately and continue processing jobs.
*
* @return void
*/ */
private function registerSigHandlers(): void private function registerSigHandlers()
{ {
if (!function_exists('pcntl_signal')) { if (!function_exists('pcntl_signal')) {
return; return;
@ -395,51 +355,43 @@ class Worker
pcntl_signal(SIGUSR1, [$this, 'killChild']); pcntl_signal(SIGUSR1, [$this, 'killChild']);
pcntl_signal(SIGUSR2, [$this, 'pauseProcessing']); pcntl_signal(SIGUSR2, [$this, 'pauseProcessing']);
pcntl_signal(SIGCONT, [$this, 'unPauseProcessing']); pcntl_signal(SIGCONT, [$this, 'unPauseProcessing']);
$this->logger->log(\Psr\Log\LogLevel::DEBUG, 'Registered signals'); $this->logger->log(Psr\Log\LogLevel::DEBUG, 'Registered signals');
} }
/** /**
* Signal handler callback for USR2, pauses processing of new jobs * Signal handler callback for USR2, pauses processing of new jobs.
*
* @return void
*/ */
public function pauseProcessing(): void public function pauseProcessing()
{ {
$this->logger->log(\Psr\Log\LogLevel::NOTICE, 'USR2 received; pausing job processing'); $this->logger->log(Psr\Log\LogLevel::NOTICE, 'USR2 received; pausing job processing');
$this->paused = true; $this->paused = true;
} }
/** /**
* Signal handler callback for CONT, resumes worker allowing it to pick * Signal handler callback for CONT, resumes worker allowing it to pick
* up new jobs. * up new jobs.
*
* @return void
*/ */
public function unPauseProcessing(): void public function unPauseProcessing()
{ {
$this->logger->log(\Psr\Log\LogLevel::NOTICE, 'CONT received; resuming job processing'); $this->logger->log(Psr\Log\LogLevel::NOTICE, 'CONT received; resuming job processing');
$this->paused = false; $this->paused = false;
} }
/** /**
* Schedule a worker for shutdown. Will finish processing the current job * Schedule a worker for shutdown. Will finish processing the current job
* and when the timeout interval is reached, the worker will shut down. * and when the timeout interval is reached, the worker will shut down.
*
* @return void
*/ */
public function shutdown(): void public function shutdown()
{ {
$this->shutdown = true; $this->shutdown = true;
$this->logger->log(\Psr\Log\LogLevel::NOTICE, 'Shutting down'); $this->logger->log(Psr\Log\LogLevel::NOTICE, 'Shutting down');
} }
/** /**
* Force an immediate shutdown of the worker, killing any child jobs * Force an immediate shutdown of the worker, killing any child jobs
* currently running. * currently running.
*
* @return void
*/ */
public function shutdownNow(): void public function shutdownNow()
{ {
$this->shutdown(); $this->shutdown();
$this->killChild(); $this->killChild();
@ -448,27 +400,21 @@ class Worker
/** /**
* Kill a forked child job immediately. The job it is processing will not * Kill a forked child job immediately. The job it is processing will not
* be completed. * be completed.
*
* @return void
*/ */
public function killChild(): void public function killChild()
{ {
if (!$this->child) { if (!$this->child) {
$this->logger->log(\Psr\Log\LogLevel::DEBUG, 'No child to kill.'); $this->logger->log(Psr\Log\LogLevel::DEBUG, 'No child to kill.');
return; return;
} }
$this->logger->log(\Psr\Log\LogLevel::INFO, 'Killing child at {child}', ['child' => $this->child]); $this->logger->log(Psr\Log\LogLevel::INFO, 'Killing child at {child}', ['child' => $this->child]);
if (exec('ps -o pid,state -p ' . $this->child, $output, $returnCode) && $returnCode != 1) { if (exec('ps -o pid,state -p ' . $this->child, $output, $returnCode) && $returnCode != 1) {
$this->logger->log(\Psr\Log\LogLevel::DEBUG, 'Child {child} found, killing.', ['child' => $this->child]); $this->logger->log(Psr\Log\LogLevel::DEBUG, 'Child {child} found, killing.', ['child' => $this->child]);
posix_kill($this->child, SIGKILL); posix_kill($this->child, SIGKILL);
$this->child = null; $this->child = null;
} else { } else {
$this->logger->log( $this->logger->log(Psr\Log\LogLevel::INFO, 'Child {child} not found, restarting.', ['child' => $this->child]);
\Psr\Log\LogLevel::INFO,
'Child {child} not found, restarting.',
['child' => $this->child],
);
$this->shutdown(); $this->shutdown();
} }
} }
@ -480,10 +426,8 @@ class Worker
* This is a form of garbage collection to handle cases where the * This is a form of garbage collection to handle cases where the
* server may have been killed and the Resque workers did not die gracefully * server may have been killed and the Resque workers did not die gracefully
* and therefore leave state information in Redis. * and therefore leave state information in Redis.
*
* @return void
*/ */
public function pruneDeadWorkers(): void public function pruneDeadWorkers()
{ {
$workerPids = $this->workerPids(); $workerPids = $this->workerPids();
$workers = self::all(); $workers = self::all();
@ -493,11 +437,7 @@ class Worker
if ($host != $this->hostname || in_array($pid, $workerPids) || $pid == getmypid()) { if ($host != $this->hostname || in_array($pid, $workerPids) || $pid == getmypid()) {
continue; continue;
} }
$this->logger->log( $this->logger->log(Psr\Log\LogLevel::INFO, 'Pruning dead worker: {worker}', ['worker' => (string)$worker]);
\Psr\Log\LogLevel::INFO,
'Pruning dead worker: {worker}',
['worker' => (string)$worker],
);
$worker->unregisterWorker(); $worker->unregisterWorker();
} }
} }
@ -509,7 +449,7 @@ class Worker
* *
* @return array Array of Resque worker process IDs. * @return array Array of Resque worker process IDs.
*/ */
public function workerPids(): array public function workerPids()
{ {
$pids = []; $pids = [];
exec('ps -A -o pid,command | grep [r]esque', $cmdOutput); exec('ps -A -o pid,command | grep [r]esque', $cmdOutput);
@ -521,122 +461,100 @@ class Worker
/** /**
* Register this worker in Redis. * Register this worker in Redis.
* 48 hour TTL so we don't pollute the redis db on server termination. * 48 hour TTL so we don't pollute the db on server termination.
*
* @return void
*/ */
public function registerWorker(): void public function registerWorker()
{ {
Resque::redis()->sadd('workers', (string)$this); Resque::redis()->sadd('workers', (string)$this);
Resque::redis()->set( Resque::redis()->setex('worker:' . (string)$this . ':started', 172800, strftime('%a %b %d %H:%M:%S %Z %Y'));
'worker:' . (string)$this . ':started',
date('D M d H:i:s T Y'),
['ex' => Redis::DEFAULT_REDIS_TTL],
);
} }
/** /**
* Unregister this worker in Redis. (shutdown etc) * Unregister this worker in Redis. (shutdown etc)
*
* @return void
*/ */
public function unregisterWorker(): void public function unregisterWorker()
{ {
if (is_object($this->currentJob)) { if (is_object($this->currentJob)) {
$this->currentJob->fail(new \Resque\Job\DirtyExitException()); $this->currentJob->fail(new Resque_Job_DirtyExitException);
} }
$id = (string)$this; $id = (string)$this;
Resque::redis()->srem('workers', $id); Resque::redis()->srem('workers', $id);
Resque::redis()->del('worker:' . $id); Resque::redis()->del('worker:' . $id);
Resque::redis()->del('worker:' . $id . ':started'); Resque::redis()->del('worker:' . $id . ':started');
Stat::clear('processed:' . $id); Resque_Stat::clear('processed:' . $id);
Stat::clear('failed:' . $id); Resque_Stat::clear('failed:' . $id);
} }
/** /**
* Tell Redis which job we're currently working on * Tell Redis which job we're currently working on.
*
* @param \Resque\Job\Job $job \Resque\Job\Job instance containing the job we're working on
*
* @return void
* *
* @param Resque_Job $job Resque_Job instance containing the job we're working on.
* @throws Resque_RedisException * @throws Resque_RedisException
*/ */
public function workingOn(\Resque\Job\Job $job): void public function workingOn(Resque_Job $job)
{ {
$job->worker = $this; $job->worker = $this;
$this->currentJob = $job; $this->currentJob = $job;
$job->updateStatus(\Resque\Job\Status::STATUS_RUNNING); $job->updateStatus(Resque_Job_Status::STATUS_RUNNING);
$data = json_encode([ $data = json_encode([
'queue' => $job->queue, 'queue' => $job->queue,
'run_at' => date('D M d H:i:s T Y'), 'run_at' => strftime('%a %b %d %H:%M:%S %Z %Y'),
'payload' => $job->payload 'payload' => $job->payload
]); ]);
Resque::redis()->set('worker:' . $job->worker, $data);
Resque::redis()->set(
'worker:' . $job->worker,
$data,
['ex' => Redis::DEFAULT_REDIS_TTL],
);
} }
/** /**
* Notify Redis that we've finished working on a job, clearing the working * Notify Redis that we've finished working on a job, clearing the working
* state and incrementing the job stats * state and incrementing the job stats.
*
* @return void
*/ */
public function doneWorking(): void public function doneWorking()
{ {
$this->currentJob = null; $this->currentJob = null;
Stat::incr('processed'); Resque_Stat::incr('processed');
Stat::incr('processed:' . (string)$this); Resque_Stat::incr('processed:' . (string)$this);
Resque::redis()->del('worker:' . (string)$this); Resque::redis()->del('worker:' . (string)$this);
} }
/** /**
* Generate a string representation of this worker * Generate a string representation of this worker.
* *
* @return string String identifier for this worker instance * @return string String identifier for this worker instance.
*/ */
public function __toString(): string public function __toString()
{ {
return (string) $this->id; return $this->id;
} }
/** /**
* Return an object describing the job this worker is currently working on * Return an object describing the job this worker is currently working on.
* *
* @return array Array with details of current job * @return array Array with details of current job.
*/ */
public function job(): array public function job(): array
{ {
$job = Resque::redis()->get('worker:' . $this); $job = Resque::redis()->get('worker:' . $this);
return $job ? json_decode($job, true) : []; return $job ? json_decode($job, true) : [];
} }
/** /**
* Get a statistic belonging to this worker * Get a statistic belonging to this worker.
* *
* @param string $stat Statistic to fetch. * @param string $stat Statistic to fetch.
*
* @return int Statistic value. * @return int Statistic value.
*/ */
public function getStat(string $stat): int public function getStat($stat)
{ {
return \Resque\Stat::get($stat . ':' . $this); return Resque_Stat::get($stat . ':' . $this);
} }
/** /**
* Inject the logging object into the worker * Inject the logging object into the worker
* *
* @param \Psr\Log\LoggerInterface $logger * @param Psr\Log\LoggerInterface $logger
*
* @return void
*/ */
public function setLogger(\Psr\Log\LoggerInterface $logger): void public function setLogger(Psr\Log\LoggerInterface $logger)
{ {
$this->logger = $logger; $this->logger = $logger;
} }

View file

@ -1,17 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<phpunit backupGlobals="false" <phpunit backupGlobals="false"
bootstrap="tests/bootstrap.php" bootstrap="test/bootstrap.php"
backupStaticAttributes="false" backupStaticAttributes="false"
colors="true" colors="true"
convertErrorsToExceptions="true" convertErrorsToExceptions="true"
convertNoticesToExceptions="true" convertNoticesToExceptions="true"
convertWarningsToExceptions="true" convertWarningsToExceptions="true"
processIsolation="true" processIsolation="false"
stopOnFailure="false" stopOnFailure="false"
syntaxCheck="false"
> >
<testsuites> <testsuites>
<testsuite name="Resque Test Suite"> <testsuite name="Resque Test Suite">
<directory>./tests/Resque/</directory> <directory>./test/Resque/</directory>
</testsuite> </testsuite>
</testsuites> </testsuites>
<filter>
<whitelist>
<directory suffix=".php">./lib/Resque/</directory>
</whitelist>
</filter>
</phpunit> </phpunit>

View file

@ -1,29 +0,0 @@
<?xml version="1.0"?>
<ruleset name="PHP82" namespace="ezyVet\PHPCS">
<description>PHP8.2 Ruleset</description>
<file>.</file>
<exclude-pattern>vendor</exclude-pattern>
<exclude-pattern>tests/</exclude-pattern>
<arg name="extensions" value="php" />
<arg name="colors"/>
<arg value="sp"/>
<arg name="parallel" value="16"/>
<arg name="report-width" value="140" />
<arg name="error-severity" value="1" />
<!-- Setting warning-severity here overrides both the '-n' CLI option and 'config-set show_warnings 0', so we
can't use it. -->
<ini name="memory_limit" value="256M"/>
<!-- Check for version support for PHP 8.2 and higher. -->
<config name="testVersion" value="8.2-"/>
<rule ref="PSR12">
</rule>
<rule ref="PHPCompatibility">
</rule>
</ruleset>

View file

@ -1,50 +0,0 @@
<?php
namespace Resque\Job;
/**
* Job Factory!
*
* @package Resque/Job
* @author Daniel Mason <daniel@m2.nz>
* @license http://www.opensource.org/licenses/mit-license.php
*/
class Factory implements FactoryInterface
{
public ?Job $job;
public string $queue;
public array $args;
/**
* Create job factory
*
* @param $className
* @param array $args
* @param $queue
*
* @return \Resque\Job\JobInterface
*
* @throws \Resque\Exception
*/
public function create($className, $args, $queue)
{
if (!class_exists($className)) {
throw new \Resque\Exception(
'Could not find job class ' . $className . '.'
);
}
if (!method_exists($className, 'perform')) {
throw new \Resque\Exception(
'Job class ' . $className . ' does not contain a perform() method.'
);
}
$instance = new $className();
$instance->args = $args;
$instance->queue = $queue;
return $instance;
}
}

View file

@ -1,22 +0,0 @@
<?php
namespace Resque\Job;
/**
* Job Interface
*
* @package Resque/Job
* @author Daniel Mason <daniel@m2.nz>
* @license http://www.opensource.org/licenses/mit-license.php
*/
interface FactoryInterface
{
/**
* @param $className
* @param array $args
* @param $queue
*
* @return \Resque\Job\JobInterface
*/
public function create($className, $args, $queue);
}

View file

@ -1,15 +0,0 @@
<?php
namespace Resque;
/**
* Redis exceptions
*
* @package Resque
* @author Daniel Mason <daniel@m2.nz>
* @license http://www.opensource.org/licenses/mit-license.php
*/
class RedisException extends \Exception
{
}

View file

@ -1,45 +1,43 @@
<?php <?php
namespace Resque\Test;
/** /**
* \Resque\Event tests. * Resque_Event tests.
* *
* @package Resque/Tests * @package Resque/Tests
* @author Daniel Mason <daniel@m2.nz> * @author Chris Boulton <chris@bigcommerce.com>
* @license http://www.opensource.org/licenses/mit-license.php * @license http://www.opensource.org/licenses/mit-license.php
*/ */
class EventTest extends TestCase class Resque_Tests_EventTest extends Resque_Tests_TestCase
{ {
private $callbacksHit = []; private $callbacksHit = [];
private $worker; private $worker;
public function setUp(): void public function setUp()
{ {
TestJob::$called = false; Test_Job::$called = false;
// Register a worker to test with // Register a worker to test with
$this->worker = new \Resque\Worker('jobs'); $this->worker = new Resque_Worker('jobs');
$this->worker->setLogger(new \Resque\Log()); $this->worker->setLogger(new Resque_Log());
$this->worker->registerWorker(); $this->worker->registerWorker();
} }
public function tearDown(): void public function tearDown()
{ {
\Resque\Event::clearListeners(); Resque_Event::clearListeners();
$this->callbacksHit = []; $this->callbacksHit = [];
} }
public function getEventTestJob() public function getEventTestJob()
{ {
$payload = [ $payload = [
'class' => '\Resque\Test\TestJob', 'class' => 'Test_Job',
'args' => [ 'args' => [
['somevar'], ['somevar'],
], ],
]; ];
$job = new \Resque\Job\Job('jobs', $payload); $job = new Resque_Job('jobs', $payload);
$job->worker = $this->worker; $job->worker = $this->worker;
return $job; return $job;
} }
@ -60,7 +58,7 @@ class EventTest extends TestCase
*/ */
public function testEventCallbacksFire($event, $callback) public function testEventCallbacksFire($event, $callback)
{ {
\Resque\Event::listen($event, [$this, $callback]); Resque_Event::listen($event, [$this, $callback]);
$job = $this->getEventTestJob(); $job = $this->getEventTestJob();
$this->worker->perform($job); $this->worker->perform($job);
@ -74,8 +72,8 @@ class EventTest extends TestCase
$event = 'beforeFork'; $event = 'beforeFork';
$callback = 'beforeForkEventCallback'; $callback = 'beforeForkEventCallback';
\Resque\Event::listen($event, [$this, $callback]); Resque_Event::listen($event, [$this, $callback]);
\Resque\Resque::enqueue('jobs', '\Resque\Test\TestJob', [ Resque::enqueue('jobs', 'Test_Job', [
'somevar' 'somevar'
]); ]);
$this->getEventTestJob(); $this->getEventTestJob();
@ -88,8 +86,8 @@ class EventTest extends TestCase
$event = 'beforeEnqueue'; $event = 'beforeEnqueue';
$callback = 'beforeEnqueueEventCallback'; $callback = 'beforeEnqueueEventCallback';
\Resque\Event::listen($event, [$this, $callback]); Resque_Event::listen($event, [$this, $callback]);
\Resque\Resque::enqueue('jobs', '\Resque\Test\TestJob', [ Resque::enqueue('jobs', 'Test_Job', [
'somevar' 'somevar'
]); ]);
$this->assertContains($callback, $this->callbacksHit, $event . ' callback (' . $callback . ') was not called'); $this->assertContains($callback, $this->callbacksHit, $event . ' callback (' . $callback . ') was not called');
@ -98,22 +96,22 @@ class EventTest extends TestCase
public function testBeforePerformEventCanStopWork() public function testBeforePerformEventCanStopWork()
{ {
$callback = 'beforePerformEventDontPerformCallback'; $callback = 'beforePerformEventDontPerformCallback';
\Resque\Event::listen('beforePerform', [$this, $callback]); Resque_Event::listen('beforePerform', [$this, $callback]);
$job = $this->getEventTestJob(); $job = $this->getEventTestJob();
$this->assertFalse($job->perform()); $this->assertFalse($job->perform());
$this->assertContains($callback, $this->callbacksHit, $callback . ' callback was not called'); $this->assertContains($callback, $this->callbacksHit, $callback . ' callback was not called');
$this->assertFalse(TestJob::$called, 'Job was still performed though Resque_Job_DontPerform was thrown'); $this->assertFalse(Test_Job::$called, 'Job was still performed though Resque_Job_DontPerform was thrown');
} }
public function testBeforeEnqueueEventStopsJobCreation() public function testBeforeEnqueueEventStopsJobCreation()
{ {
$callback = 'beforeEnqueueEventDontCreateCallback'; $callback = 'beforeEnqueueEventDontCreateCallback';
\Resque\Event::listen('beforeEnqueue', [$this, $callback]); Resque_Event::listen('beforeEnqueue', [$this, $callback]);
\Resque\Event::listen('afterEnqueue', [$this, 'afterEnqueueEventCallback']); Resque_Event::listen('afterEnqueue', [$this, 'afterEnqueueEventCallback']);
$result = \Resque\Resque::enqueue('jobs', '\Resque\Test\TestClass'); $result = Resque::enqueue('test_job', 'TestClass');
$this->assertContains($callback, $this->callbacksHit, $callback . ' callback was not called'); $this->assertContains($callback, $this->callbacksHit, $callback . ' callback was not called');
$this->assertNotContains('afterEnqueueEventCallback', $this->callbacksHit, 'afterEnqueue was still called, even though it should not have been'); $this->assertNotContains('afterEnqueueEventCallback', $this->callbacksHit, 'afterEnqueue was still called, even though it should not have been');
$this->assertFalse($result); $this->assertFalse($result);
@ -124,8 +122,8 @@ class EventTest extends TestCase
$callback = 'afterEnqueueEventCallback'; $callback = 'afterEnqueueEventCallback';
$event = 'afterEnqueue'; $event = 'afterEnqueue';
\Resque\Event::listen($event, [$this, $callback]); Resque_Event::listen($event, [$this, $callback]);
\Resque\Resque::enqueue('jobs', '\Resque\Test\TestJob', [ Resque::enqueue('jobs', 'Test_Job', [
'somevar' 'somevar'
]); ]);
$this->assertContains($callback, $this->callbacksHit, $event . ' callback (' . $callback . ') was not called'); $this->assertContains($callback, $this->callbacksHit, $event . ' callback (' . $callback . ') was not called');
@ -136,8 +134,8 @@ class EventTest extends TestCase
$callback = 'beforePerformEventCallback'; $callback = 'beforePerformEventCallback';
$event = 'beforePerform'; $event = 'beforePerform';
\Resque\Event::listen($event, [$this, $callback]); Resque_Event::listen($event, [$this, $callback]);
\Resque\Event::stopListening($event, [$this, $callback]); Resque_Event::stopListening($event, [$this, $callback]);
$job = $this->getEventTestJob(); $job = $this->getEventTestJob();
$this->worker->perform($job); $this->worker->perform($job);
@ -151,20 +149,20 @@ class EventTest extends TestCase
public function beforePerformEventDontPerformCallback() public function beforePerformEventDontPerformCallback()
{ {
$this->callbacksHit[] = __FUNCTION__; $this->callbacksHit[] = __FUNCTION__;
throw new \Resque\Job\DontPerform(); throw new Resque_Job_DontPerform();
} }
public function beforeEnqueueEventDontCreateCallback() public function beforeEnqueueEventDontCreateCallback()
{ {
$this->callbacksHit[] = __FUNCTION__; $this->callbacksHit[] = __FUNCTION__;
throw new \Resque\Job\DontCreate(); throw new Resque_Job_DontCreate();
} }
public function assertValidEventCallback($function, $job) public function assertValidEventCallback($function, $job)
{ {
$this->callbacksHit[] = $function; $this->callbacksHit[] = $function;
if (!$job instanceof \Resque\Job\Job) { if (!$job instanceof Resque_Job) {
$this->fail('Callback job argument is not an instance of \Resque\Job\Job'); $this->fail('Callback job argument is not an instance of Resque_Job');
} }
$args = $job->getArguments(); $args = $job->getArguments();
$this->assertEquals($args[0], 'somevar'); $this->assertEquals($args[0], 'somevar');
@ -173,7 +171,7 @@ class EventTest extends TestCase
public function afterEnqueueEventCallback($class, $args) public function afterEnqueueEventCallback($class, $args)
{ {
$this->callbacksHit[] = __FUNCTION__; $this->callbacksHit[] = __FUNCTION__;
$this->assertEquals('\Resque\Test\TestJob', $class); $this->assertEquals('Test_Job', $class);
$this->assertEquals([ $this->assertEquals([
'somevar', 'somevar',
], $args); ], $args);

View file

@ -0,0 +1,109 @@
<?php
/**
* Resque_Job_Status tests.
*
* @package Resque/Tests
* @author Chris Boulton <chris@bigcommerce.com>
* @license http://www.opensource.org/licenses/mit-license.php
*/
class Resque_Tests_JobStatusTest extends Resque_Tests_TestCase
{
/**
* @var \Resque_Worker
*/
protected $worker;
public function setUp()
{
parent::setUp();
// Register a worker to test with
$this->worker = new Resque_Worker('jobs');
$this->worker->setLogger(new Resque_Log());
}
public function testJobStatusCanBeTracked()
{
$token = Resque::enqueue('jobs', 'Test_Job', null, true);
$status = new Resque_Job_Status($token);
$this->assertTrue($status->isTracking());
}
public function testJobStatusIsReturnedViaJobInstance()
{
Resque::enqueue('jobs', 'Test_Job', null, true);
$job = Resque_Job::reserve('jobs');
$this->assertEquals(Resque_Job_Status::STATUS_WAITING, $job->getStatus());
}
public function testQueuedJobReturnsQueuedStatus()
{
$token = Resque::enqueue('jobs', 'Test_Job', null, true);
$status = new Resque_Job_Status($token);
$this->assertEquals(Resque_Job_Status::STATUS_WAITING, $status->get());
}
public function testRunningJobReturnsRunningStatus()
{
$token = Resque::enqueue('jobs', 'Failing_Job', null, true);
$job = $this->worker->reserve();
$this->worker->workingOn($job);
$status = new Resque_Job_Status($token);
$this->assertEquals(Resque_Job_Status::STATUS_RUNNING, $status->get());
}
public function testFailedJobReturnsFailedStatus()
{
$token = Resque::enqueue('jobs', 'Failing_Job', null, true);
$this->worker->work(0);
$status = new Resque_Job_Status($token);
$this->assertEquals(Resque_Job_Status::STATUS_FAILED, $status->get());
}
public function testCompletedJobReturnsCompletedStatus()
{
$token = Resque::enqueue('jobs', 'Test_Job', null, true);
$this->worker->work(0);
$status = new Resque_Job_Status($token);
$this->assertEquals(Resque_Job_Status::STATUS_COMPLETE, $status->get());
}
public function testStatusIsNotTrackedWhenToldNotTo()
{
$token = Resque::enqueue('jobs', 'Test_Job', null, false);
$status = new Resque_Job_Status($token);
$this->assertFalse($status->isTracking());
}
public function testStatusTrackingCanBeStopped()
{
Resque_Job_Status::create('test');
$status = new Resque_Job_Status('test');
$this->assertEquals(Resque_Job_Status::STATUS_WAITING, $status->get());
$status->stop();
$this->assertFalse($status->get());
}
public function testRecreatedJobWithTrackingStillTracksStatus()
{
$originalToken = Resque::enqueue('jobs', 'Test_Job', null, true);
$job = $this->worker->reserve();
// Mark this job as being worked on to ensure that the new status is still
// waiting.
$this->worker->workingOn($job);
// Now recreate it
$newToken = $job->recreate();
// Make sure we've got a new job returned
$this->assertNotEquals($originalToken, $newToken);
// Now check the status of the new job
$newJob = Resque_Job::reserve('jobs');
$this->assertEquals(Resque_Job_Status::STATUS_WAITING, $newJob->getStatus());
}
}

View file

@ -0,0 +1,417 @@
<?php
/**
* Resque_Job tests.
*
* @package Resque/Tests
* @author Chris Boulton <chris@bigcommerce.com>
* @license http://www.opensource.org/licenses/mit-license.php
*/
class Resque_Tests_JobTest extends Resque_Tests_TestCase
{
protected $worker;
public function setUp()
{
parent::setUp();
// Register a worker to test with
$this->worker = new Resque_Worker('jobs');
$this->worker->setLogger(new Resque_Log());
$this->worker->registerWorker();
}
public function testJobCanBeQueued()
{
$this->assertTrue((bool)Resque::enqueue('jobs', 'Test_Job'));
}
public function testQeueuedJobCanBeReserved()
{
Resque::enqueue('jobs', 'Test_Job');
$job = Resque_Job::reserve('jobs');
if ($job == false) {
$this->fail('Job could not be reserved.');
}
$this->assertEquals('jobs', $job->queue);
$this->assertEquals('Test_Job', $job->payload['class']);
}
/**
* @expectedException InvalidArgumentException
*/
public function testObjectArgumentsCannotBePassedToJob()
{
$args = new stdClass;
$args->test = 'somevalue';
Resque::enqueue('jobs', 'Test_Job', $args);
}
public function testQueuedJobReturnsExactSamePassedInArguments()
{
$args = [
'int' => 123,
'numArray' => [
1,
2,
],
'assocArray' => [
'key1' => 'value1',
'key2' => 'value2'
],
];
Resque::enqueue('jobs', 'Test_Job', $args);
$job = Resque_Job::reserve('jobs');
$this->assertEquals($args, $job->getArguments());
}
public function testAfterJobIsReservedItIsRemoved()
{
Resque::enqueue('jobs', 'Test_Job');
Resque_Job::reserve('jobs');
$this->assertFalse(Resque_Job::reserve('jobs'));
}
public function testRecreatedJobMatchesExistingJob()
{
$args = [
'int' => 123,
'numArray' => [
1,
2,
],
'assocArray' => [
'key1' => 'value1',
'key2' => 'value2'
],
];
Resque::enqueue('jobs', 'Test_Job', $args);
$job = Resque_Job::reserve('jobs');
// Now recreate it
$job->recreate();
$newJob = Resque_Job::reserve('jobs');
$this->assertEquals($job->payload['class'], $newJob->payload['class']);
$this->assertEquals($job->getArguments(), $newJob->getArguments());
}
public function testFailedJobExceptionsAreCaught()
{
$payload = [
'class' => 'Failing_Job',
'args' => null
];
$job = new Resque_Job('jobs', $payload);
$job->worker = $this->worker;
$this->worker->perform($job);
$this->assertEquals(1, Resque_Stat::get('failed'));
$this->assertEquals(1, Resque_Stat::get('failed:' . $this->worker));
}
/**
* @expectedException Resque_Exception
*/
public function testJobWithoutPerformMethodThrowsException()
{
Resque::enqueue('jobs', 'Test_Job_Without_Perform_Method');
$job = $this->worker->reserve();
$job->worker = $this->worker;
$job->perform();
}
/**
* @expectedException Resque_Exception
*/
public function testInvalidJobThrowsException()
{
Resque::enqueue('jobs', 'Invalid_Job');
$job = $this->worker->reserve();
$job->worker = $this->worker;
$job->perform();
}
public function testJobWithSetUpCallbackFiresSetUp()
{
$payload = [
'class' => 'Test_Job_With_SetUp',
'args' => [
'somevar',
'somevar2',
],
];
$job = new Resque_Job('jobs', $payload);
$job->perform();
$this->assertTrue(Test_Job_With_SetUp::$called);
}
public function testJobWithTearDownCallbackFiresTearDown()
{
$payload = [
'class' => 'Test_Job_With_TearDown',
'args' => [
'somevar',
'somevar2',
],
];
$job = new Resque_Job('jobs', $payload);
$job->perform();
$this->assertTrue(Test_Job_With_TearDown::$called);
}
public function testNamespaceNaming()
{
$fixture = [
['test' => 'more:than:one:with:', 'assertValue' => 'more:than:one:with:'],
['test' => 'more:than:one:without', 'assertValue' => 'more:than:one:without:'],
['test' => 'resque', 'assertValue' => 'resque:'],
['test' => 'resque:', 'assertValue' => 'resque:'],
];
foreach ($fixture as $item) {
Resque_Redis::prefix($item['test']);
$this->assertEquals(Resque_Redis::getPrefix(), $item['assertValue']);
}
}
public function testJobWithNamespace()
{
Resque_Redis::prefix('php');
$queue = 'jobs';
$payload = ['another_value'];
Resque::enqueue($queue, 'Test_Job_With_TearDown', $payload);
$this->assertEquals(Resque::queues(), ['jobs']);
$this->assertEquals(Resque::size($queue), 1);
Resque_Redis::prefix('resque');
$this->assertEquals(Resque::size($queue), 0);
}
public function testDequeueAll()
{
$queue = 'jobs';
Resque::enqueue($queue, 'Test_Job_Dequeue');
Resque::enqueue($queue, 'Test_Job_Dequeue');
$this->assertEquals(Resque::size($queue), 2);
$this->assertEquals(Resque::dequeue($queue), 2);
$this->assertEquals(Resque::size($queue), 0);
}
public function testDequeueMakeSureNotDeleteOthers()
{
$queue = 'jobs';
Resque::enqueue($queue, 'Test_Job_Dequeue');
Resque::enqueue($queue, 'Test_Job_Dequeue');
$other_queue = 'other_jobs';
Resque::enqueue($other_queue, 'Test_Job_Dequeue');
Resque::enqueue($other_queue, 'Test_Job_Dequeue');
$this->assertEquals(Resque::size($queue), 2);
$this->assertEquals(Resque::size($other_queue), 2);
$this->assertEquals(Resque::dequeue($queue), 2);
$this->assertEquals(Resque::size($queue), 0);
$this->assertEquals(Resque::size($other_queue), 2);
}
public function testDequeueSpecificItem()
{
$queue = 'jobs';
Resque::enqueue($queue, 'Test_Job_Dequeue1');
Resque::enqueue($queue, 'Test_Job_Dequeue2');
$this->assertEquals(Resque::size($queue), 2);
$test = ['Test_Job_Dequeue2'];
$this->assertEquals(Resque::dequeue($queue, $test), 1);
$this->assertEquals(Resque::size($queue), 1);
}
public function testDequeueSpecificMultipleItems()
{
$queue = 'jobs';
Resque::enqueue($queue, 'Test_Job_Dequeue1');
Resque::enqueue($queue, 'Test_Job_Dequeue2');
Resque::enqueue($queue, 'Test_Job_Dequeue3');
$this->assertEquals(Resque::size($queue), 3);
$test = ['Test_Job_Dequeue2', 'Test_Job_Dequeue3'];
$this->assertEquals(Resque::dequeue($queue, $test), 2);
$this->assertEquals(Resque::size($queue), 1);
}
public function testDequeueNonExistingItem()
{
$queue = 'jobs';
Resque::enqueue($queue, 'Test_Job_Dequeue1');
Resque::enqueue($queue, 'Test_Job_Dequeue2');
Resque::enqueue($queue, 'Test_Job_Dequeue3');
$this->assertEquals(Resque::size($queue), 3);
$test = ['Test_Job_Dequeue4'];
$this->assertEquals(Resque::dequeue($queue, $test), 0);
$this->assertEquals(Resque::size($queue), 3);
}
public function testDequeueNonExistingItem2()
{
$queue = 'jobs';
Resque::enqueue($queue, 'Test_Job_Dequeue1');
Resque::enqueue($queue, 'Test_Job_Dequeue2');
Resque::enqueue($queue, 'Test_Job_Dequeue3');
$this->assertEquals(Resque::size($queue), 3);
$test = ['Test_Job_Dequeue4', 'Test_Job_Dequeue1'];
$this->assertEquals(Resque::dequeue($queue, $test), 1);
$this->assertEquals(Resque::size($queue), 2);
}
public function testDequeueItemID()
{
$queue = 'jobs';
Resque::enqueue($queue, 'Test_Job_Dequeue');
$qid = Resque::enqueue($queue, 'Test_Job_Dequeue');
$this->assertEquals(Resque::size($queue), 2);
$test = ['Test_Job_Dequeue' => $qid];
$this->assertEquals(Resque::dequeue($queue, $test), 1);
$this->assertEquals(Resque::size($queue), 1);
}
public function testDequeueWrongItemID()
{
$queue = 'jobs';
Resque::enqueue($queue, 'Test_Job_Dequeue');
$qid = Resque::enqueue($queue, 'Test_Job_Dequeue');
$this->assertEquals(Resque::size($queue), 2);
#qid right but class name is wrong
$test = ['Test_Job_Dequeue1' => $qid];
$this->assertEquals(Resque::dequeue($queue, $test), 0);
$this->assertEquals(Resque::size($queue), 2);
}
public function testDequeueWrongItemID2()
{
$queue = 'jobs';
Resque::enqueue($queue, 'Test_Job_Dequeue');
Resque::enqueue($queue, 'Test_Job_Dequeue');
$this->assertEquals(Resque::size($queue), 2);
$test = ['Test_Job_Dequeue' => 'r4nD0mH4sh3dId'];
$this->assertEquals(Resque::dequeue($queue, $test), 0);
$this->assertEquals(Resque::size($queue), 2);
}
public function testDequeueItemWithArg()
{
$queue = 'jobs';
$arg = ['foo' => 1, 'bar' => 2];
Resque::enqueue($queue, 'Test_Job_Dequeue9');
Resque::enqueue($queue, 'Test_Job_Dequeue9', $arg);
$this->assertEquals(Resque::size($queue), 2);
$test = ['Test_Job_Dequeue9' => $arg];
$this->assertEquals(Resque::dequeue($queue, $test), 1);
#$this->assertEquals(Resque::size($queue), 1);
}
public function testDequeueSeveralItemsWithArgs()
{
// GIVEN
$queue = 'jobs';
$args = ['foo' => 1, 'bar' => 10];
$removeArgs = ['foo' => 1, 'bar' => 2];
Resque::enqueue($queue, 'Test_Job_Dequeue9', $args);
Resque::enqueue($queue, 'Test_Job_Dequeue9', $removeArgs);
Resque::enqueue($queue, 'Test_Job_Dequeue9', $removeArgs);
$this->assertEquals(Resque::size($queue), 3, "Failed to add 3 items.");
// WHEN
$test = ['Test_Job_Dequeue9' => $removeArgs];
$removedItems = Resque::dequeue($queue, $test);
// THEN
$this->assertEquals($removedItems, 2);
$this->assertEquals(Resque::size($queue), 1);
$item = Resque::pop($queue);
$this->assertInternalType('array', $item['args']);
$this->assertEquals(10, $item['args'][0]['bar'], 'Wrong items were dequeued from queue!');
}
public function testDequeueItemWithUnorderedArg()
{
$queue = 'jobs';
$arg = ['foo' => 1, 'bar' => 2];
$arg2 = ['bar' => 2, 'foo' => 1];
Resque::enqueue($queue, 'Test_Job_Dequeue');
Resque::enqueue($queue, 'Test_Job_Dequeue', $arg);
$this->assertEquals(Resque::size($queue), 2);
$test = ['Test_Job_Dequeue' => $arg2];
$this->assertEquals(Resque::dequeue($queue, $test), 1);
$this->assertEquals(Resque::size($queue), 1);
}
public function testDequeueItemWithiWrongArg()
{
$queue = 'jobs';
$arg = ['foo' => 1, 'bar' => 2];
$arg2 = ['foo' => 2, 'bar' => 3];
Resque::enqueue($queue, 'Test_Job_Dequeue');
Resque::enqueue($queue, 'Test_Job_Dequeue', $arg);
$this->assertEquals(Resque::size($queue), 2);
$test = ['Test_Job_Dequeue' => $arg2];
$this->assertEquals(Resque::dequeue($queue, $test), 0);
$this->assertEquals(Resque::size($queue), 2);
}
public function testUseDefaultFactoryToGetJobInstance()
{
$payload = [
'class' => 'Some_Job_Class',
'args' => null
];
$job = new Resque_Job('jobs', $payload);
$instance = $job->getInstance();
$this->assertInstanceOf('Some_Job_Class', $instance);
}
public function testUseFactoryToGetJobInstance()
{
$payload = [
'class' => 'Some_Job_Class',
'args' => [[]]
];
$job = new Resque_Job('jobs', $payload);
$factory = new Some_Stub_Factory();
$job->setJobFactory($factory);
$instance = $job->getInstance();
$this->assertInstanceOf('Resque_JobInterface', $instance);
}
}
class Some_Job_Class implements Resque_JobInterface
{
/**
* @return bool
*/
public function perform()
{
return true;
}
}
class Some_Stub_Factory implements Resque_Job_FactoryInterface
{
/**
* @param $className
* @param array $args
* @param $queue
* @return Resque_JobInterface
*/
public function create($className, $args, $queue)
{
return new Some_Job_Class();
}
}

View file

@ -1,20 +1,18 @@
<?php <?php
namespace Resque\Test;
/** /**
* \Resque\Log tests. * Resque_Log tests.
* *
* @package Resque/Tests * @package Resque/Tests
* @author Daniel Mason <daniel@m2.nz> * @author Chris Boulton <chris@bigcommerce.com>
* @license http://www.opensource.org/licenses/mit-license.php * @license http://www.opensource.org/licenses/mit-license.php
*/ */
class LogTest extends TestCase class Resque_Tests_LogTest extends Resque_Tests_TestCase
{ {
public function testLogInterpolate() public function testLogInterpolate()
{ {
$logger = new \Resque\Log(); $logger = new Resque_Log();
$actual = $logger->interpolate('string {replace}', ['replace' => 'value']); $actual = $logger->interpolate('string {replace}', ['replace' => 'value']);
$expected = 'string value'; $expected = 'string value';
@ -23,7 +21,7 @@ class LogTest extends TestCase
public function testLogInterpolateMutiple() public function testLogInterpolateMutiple()
{ {
$logger = new \Resque\Log(); $logger = new Resque_Log();
$actual = $logger->interpolate( $actual = $logger->interpolate(
'string {replace1} {replace2}', 'string {replace1} {replace2}',
['replace1' => 'value1', 'replace2' => 'value2'] ['replace1' => 'value1', 'replace2' => 'value2']

View file

@ -1,25 +1,18 @@
<?php <?php
namespace Resque\Test;
/** /**
* Resque_Event tests. * Resque_Event tests.
* *
* @package Resque/Tests * @package Resque/Tests
* @author Daniel Mason <daniel@m2.nz> * @author Chris Boulton <chris@bigcommerce.com>
* @license http://www.opensource.org/licenses/mit-license.php * @license http://www.opensource.org/licenses/mit-license.php
*/ */
class RedisTest extends TestCase class Resque_Tests_RedisTest extends Resque_Tests_TestCase
{ {
public function testRedisGetSet() public function testRedisGetSet()
{ {
$this->redis->set( $this->redis->set("testKey", 24);
'testKey',
24,
['ex' => \Resque\Redis::DEFAULT_REDIS_TTL],
);
$val = $this->redis->get("testKey"); $val = $this->redis->get("testKey");
$this->assertEquals(24, $val); $this->assertEquals(24, $val);
} }
@ -35,14 +28,14 @@ class RedisTest extends TestCase
// Input , Expected output // Input , Expected output
['', [ ['', [
'localhost', 'localhost',
\Resque\Redis::DEFAULT_PORT, Resque_Redis::DEFAULT_PORT,
false, false,
false, false, false, false,
[], [],
]], ]],
['localhost', [ ['localhost', [
'localhost', 'localhost',
\Resque\Redis::DEFAULT_PORT, Resque_Redis::DEFAULT_PORT,
false, false,
false, false, false, false,
[], [],
@ -63,14 +56,14 @@ class RedisTest extends TestCase
]], ]],
['redis://foobar', [ ['redis://foobar', [
'foobar', 'foobar',
\Resque\Redis::DEFAULT_PORT, Resque_Redis::DEFAULT_PORT,
false, false,
false, false, false, false,
[], [],
]], ]],
['redis://foobar/', [ ['redis://foobar/', [
'foobar', 'foobar',
\Resque\Redis::DEFAULT_PORT, Resque_Redis::DEFAULT_PORT,
false, false,
false, false, false, false,
[], [],
@ -182,20 +175,18 @@ class RedisTest extends TestCase
*/ */
public function testParsingValidDsnString($dsn, $expected) public function testParsingValidDsnString($dsn, $expected)
{ {
$result = \Resque\Redis::parseDsn($dsn); $result = Resque_Redis::parseDsn($dsn);
$this->assertEquals($expected, $result); $this->assertEquals($expected, $result);
} }
/** /**
* @dataProvider bogusDsnStringProvider * @dataProvider bogusDsnStringProvider
* * @expectedException InvalidArgumentException
* @expectedException \InvalidArgumentException
*
* @param $dsn * @param $dsn
*/ */
public function testParsingBogusDsnStringThrowsException($dsn) public function testParsingBogusDsnStringThrowsException($dsn)
{ {
$this->expectException(\InvalidArgumentException::class); // The next line should throw an InvalidArgumentException
\Resque\Redis::parseDsn($dsn); Resque_Redis::parseDsn($dsn);
} }
} }

View file

@ -1,53 +1,51 @@
<?php <?php
namespace Resque\Test;
/** /**
* Resque\Stat tests. * Resque_Stat tests.
* *
* @package Resque/Tests * @package Resque/Tests
* @author Daniel Mason <daniel@m2.nz> * @author Chris Boulton <chris@bigcommerce.com>
* @license http://www.opensource.org/licenses/mit-license.php * @license http://www.opensource.org/licenses/mit-license.php
*/ */
class StatTest extends TestCase class Resque_Tests_StatTest extends Resque_Tests_TestCase
{ {
public function testStatCanBeIncremented() public function testStatCanBeIncremented()
{ {
\Resque\Stat::incr('test_incr'); Resque_Stat::incr('test_incr');
\Resque\Stat::incr('test_incr'); Resque_Stat::incr('test_incr');
$this->assertEquals(2, $this->redis->get('resque:stat:test_incr')); $this->assertEquals(2, $this->redis->get('resque:stat:test_incr'));
} }
public function testStatCanBeIncrementedByX() public function testStatCanBeIncrementedByX()
{ {
\Resque\Stat::incr('test_incrX', 10); Resque_Stat::incr('test_incrX', 10);
\Resque\Stat::incr('test_incrX', 11); Resque_Stat::incr('test_incrX', 11);
$this->assertEquals(21, $this->redis->get('resque:stat:test_incrX')); $this->assertEquals(21, $this->redis->get('resque:stat:test_incrX'));
} }
public function testStatCanBeDecremented() public function testStatCanBeDecremented()
{ {
\Resque\Stat::incr('test_decr', 22); Resque_Stat::incr('test_decr', 22);
\Resque\Stat::decr('test_decr'); Resque_Stat::decr('test_decr');
$this->assertEquals(21, $this->redis->get('resque:stat:test_decr')); $this->assertEquals(21, $this->redis->get('resque:stat:test_decr'));
} }
public function testStatCanBeDecrementedByX() public function testStatCanBeDecrementedByX()
{ {
\Resque\Stat::incr('test_decrX', 22); Resque_Stat::incr('test_decrX', 22);
\Resque\Stat::decr('test_decrX', 11); Resque_Stat::decr('test_decrX', 11);
$this->assertEquals(11, $this->redis->get('resque:stat:test_decrX')); $this->assertEquals(11, $this->redis->get('resque:stat:test_decrX'));
} }
public function testGetStatByName() public function testGetStatByName()
{ {
\Resque\Stat::incr('test_get', 100); Resque_Stat::incr('test_get', 100);
$this->assertEquals(100, \Resque\Stat::get('test_get')); $this->assertEquals(100, Resque_Stat::get('test_get'));
} }
public function testGetUnknownStatReturns0() public function testGetUnknownStatReturns0()
{ {
$this->assertEquals(0, \Resque\Stat::get('test_get_unknown')); $this->assertEquals(0, Resque_Stat::get('test_get_unknown'));
} }
} }

View file

@ -1,31 +1,28 @@
<?php <?php
namespace Resque\Test;
/** /**
* Resque test case class. Contains setup and teardown methods. * Resque test case class. Contains setup and teardown methods.
* *
* @package Resque/Tests * @package Resque/Tests
* @author Daniel Mason <daniel@m2.nz> * @author Chris Boulton <chris@bigcommerce.com>
* @license http://www.opensource.org/licenses/mit-license.php * @license http://www.opensource.org/licenses/mit-license.php
*/ */
class TestCase extends \PHPUnit\Framework\TestCase
class Resque_Tests_TestCase extends PHPUnit\Framework\TestCase
{ {
protected $resque; protected $resque;
protected $redis; protected $redis;
public static function setUpBeforeClass(): void public static function setUpBeforeClass()
{ {
date_default_timezone_set('UTC'); date_default_timezone_set('UTC');
} }
public function setUp(): void public function setUp()
{ {
// Setup redis connection for testing. // Setup redis connection for testing.
global $redisTestServer; $this->redis = new Credis_Client('localhost', '6379');
Resque::setBackend('localhost');
$this->redis = new \Credis_Client($redisTestServer, '6379');
\Resque\Resque::setBackend($redisTestServer);
$this->redis->flushAll(); $this->redis->flushAll();
} }
} }

View file

@ -1,21 +1,19 @@
<?php <?php
namespace Resque\Test;
/** /**
* \Resque\Worker tests. * Resque_Worker tests.
* *
* @package Resque/Tests * @package Resque/Tests
* @author Daniel Mason <daniel@m2.nz> * @author Chris Boulton <chris@bigcommerce.com>
* @license http://www.opensource.org/licenses/mit-license.php * @license http://www.opensource.org/licenses/mit-license.php
*/ */
class WorkerTest extends TestCase class Resque_Tests_WorkerTest extends Resque_Tests_TestCase
{ {
public function testWorkerRegistersInList() public function testWorkerRegistersInList()
{ {
$worker = new \Resque\Worker('*'); $worker = new Resque_Worker('*');
$worker->setLogger(new \Resque\Log()); $worker->setLogger(new Resque_Log());
$worker->registerWorker(); $worker->registerWorker();
// Make sure the worker is in the list // Make sure the worker is in the list
@ -27,76 +25,76 @@ class WorkerTest extends TestCase
$num = 3; $num = 3;
// Register a few workers // Register a few workers
for ($i = 0; $i < $num; ++$i) { for ($i = 0; $i < $num; ++$i) {
$worker = new \Resque\Worker('queue_' . $i); $worker = new Resque_Worker('queue_' . $i);
$worker->setLogger(new \Resque\Log()); $worker->setLogger(new Resque_Log());
$worker->registerWorker(); $worker->registerWorker();
} }
// Now try to get them // Now try to get them
$this->assertEquals($num, count(\Resque\Worker::all())); $this->assertEquals($num, count(Resque_Worker::all()));
} }
public function testGetWorkerById() public function testGetWorkerById()
{ {
$worker = new \Resque\Worker('*'); $worker = new Resque_Worker('*');
$worker->setLogger(new \Resque\Log()); $worker->setLogger(new Resque_Log());
$worker->registerWorker(); $worker->registerWorker();
$newWorker = \Resque\Worker::find((string)$worker); $newWorker = Resque_Worker::find((string)$worker);
$this->assertEquals((string)$worker, (string)$newWorker); $this->assertEquals((string)$worker, (string)$newWorker);
} }
public function testInvalidWorkerDoesNotExist() public function testInvalidWorkerDoesNotExist()
{ {
$this->assertFalse(\Resque\Worker::exists('blah')); $this->assertFalse(Resque_Worker::exists('blah'));
} }
public function testWorkerCanUnregister() public function testWorkerCanUnregister()
{ {
$worker = new \Resque\Worker('*'); $worker = new Resque_Worker('*');
$worker->setLogger(new \Resque\Log()); $worker->setLogger(new Resque_Log());
$worker->registerWorker(); $worker->registerWorker();
$worker->unregisterWorker(); $worker->unregisterWorker();
$this->assertFalse(\Resque\Worker::exists((string)$worker)); $this->assertFalse(Resque_Worker::exists((string)$worker));
$this->assertEquals([], \Resque\Worker::all()); $this->assertEquals([], Resque_Worker::all());
$this->assertEquals([], $this->redis->smembers('resque:workers')); $this->assertEquals([], $this->redis->smembers('resque:workers'));
} }
public function testPausedWorkerDoesNotPickUpJobs() public function testPausedWorkerDoesNotPickUpJobs()
{ {
$worker = new \Resque\Worker('*'); $worker = new Resque_Worker('*');
$worker->setLogger(new \Resque\Log()); $worker->setLogger(new Resque_Log());
$worker->pauseProcessing(); $worker->pauseProcessing();
\Resque\Resque::enqueue('jobs', '\Resque\Test\TestJob'); Resque::enqueue('jobs', 'Test_Job');
$worker->work(0); $worker->work(0);
$worker->work(0); $worker->work(0);
$this->assertEquals(0, \Resque\Stat::get('processed')); $this->assertEquals(0, Resque_Stat::get('processed'));
} }
public function testResumedWorkerPicksUpJobs() public function testResumedWorkerPicksUpJobs()
{ {
$worker = new \Resque\Worker('*'); $worker = new Resque_Worker('*');
$worker->setLogger(new \Resque\Log()); $worker->setLogger(new Resque_Log());
$worker->pauseProcessing(); $worker->pauseProcessing();
\Resque\Resque::enqueue('jobs', '\Resque\Test\TestJob'); Resque::enqueue('jobs', 'Test_Job');
$worker->work(0); $worker->work(0);
$this->assertEquals(0, \Resque\Stat::get('processed')); $this->assertEquals(0, Resque_Stat::get('processed'));
$worker->unPauseProcessing(); $worker->unPauseProcessing();
$worker->work(0); $worker->work(0);
$this->assertEquals(1, \Resque\Stat::get('processed')); $this->assertEquals(1, Resque_Stat::get('processed'));
} }
public function testWorkerCanWorkOverMultipleQueues() public function testWorkerCanWorkOverMultipleQueues()
{ {
$worker = new \Resque\Worker([ $worker = new Resque_Worker([
'queue1', 'queue1',
'queue2' 'queue2'
]); ]);
$worker->setLogger(new \Resque\Log()); $worker->setLogger(new Resque_Log());
$worker->registerWorker(); $worker->registerWorker();
\Resque\Resque::enqueue('queue1', '\Resque\Test\TestJob_1'); Resque::enqueue('queue1', 'Test_Job_1');
\Resque\Resque::enqueue('queue2', '\Resque\Test\TestJob_2'); Resque::enqueue('queue2', 'Test_Job_2');
$job = $worker->reserve(); $job = $worker->reserve();
$this->assertEquals('queue1', $job->queue); $this->assertEquals('queue1', $job->queue);
@ -107,18 +105,18 @@ class WorkerTest extends TestCase
public function testWorkerWorksQueuesInSpecifiedOrder() public function testWorkerWorksQueuesInSpecifiedOrder()
{ {
$worker = new \Resque\Worker([ $worker = new Resque_Worker([
'high', 'high',
'medium', 'medium',
'low' 'low'
]); ]);
$worker->setLogger(new \Resque\Log()); $worker->setLogger(new Resque_Log());
$worker->registerWorker(); $worker->registerWorker();
// Queue the jobs in a different order // Queue the jobs in a different order
\Resque\Resque::enqueue('low', '\Resque\Test\TestJob_1'); Resque::enqueue('low', 'Test_Job_1');
\Resque\Resque::enqueue('high', '\Resque\Test\TestJob_2'); Resque::enqueue('high', 'Test_Job_2');
\Resque\Resque::enqueue('medium', '\Resque\Test\TestJob_3'); Resque::enqueue('medium', 'Test_Job_3');
// Now check we get the jobs back in the right order // Now check we get the jobs back in the right order
$job = $worker->reserve(); $job = $worker->reserve();
@ -133,12 +131,12 @@ class WorkerTest extends TestCase
public function testWildcardQueueWorkerWorksAllQueues() public function testWildcardQueueWorkerWorksAllQueues()
{ {
$worker = new \Resque\Worker('*'); $worker = new Resque_Worker('*');
$worker->setLogger(new \Resque\Log()); $worker->setLogger(new Resque_Log());
$worker->registerWorker(); $worker->registerWorker();
\Resque\Resque::enqueue('queue1', '\Resque\Test\TestJob_1'); Resque::enqueue('queue1', 'Test_Job_1');
\Resque\Resque::enqueue('queue2', '\Resque\Test\TestJob_2'); Resque::enqueue('queue2', 'Test_Job_2');
$job = $worker->reserve(); $job = $worker->reserve();
$this->assertEquals('queue1', $job->queue); $this->assertEquals('queue1', $job->queue);
@ -149,19 +147,19 @@ class WorkerTest extends TestCase
public function testWorkerDoesNotWorkOnUnknownQueues() public function testWorkerDoesNotWorkOnUnknownQueues()
{ {
$worker = new \Resque\Worker('queue1'); $worker = new Resque_Worker('queue1');
$worker->setLogger(new \Resque\Log()); $worker->setLogger(new Resque_Log());
$worker->registerWorker(); $worker->registerWorker();
\Resque\Resque::enqueue('queue2', '\Resque\Test\TestJob'); Resque::enqueue('queue2', 'Test_Job');
$this->assertFalse($worker->reserve()); $this->assertFalse($worker->reserve());
} }
public function testWorkerClearsItsStatusWhenNotWorking() public function testWorkerClearsItsStatusWhenNotWorking()
{ {
\Resque\Resque::enqueue('jobs', '\Resque\Test\TestJob'); Resque::enqueue('jobs', 'Test_Job');
$worker = new \Resque\Worker('jobs'); $worker = new Resque_Worker('jobs');
$worker->setLogger(new \Resque\Log()); $worker->setLogger(new Resque_Log());
$job = $worker->reserve(); $job = $worker->reserve();
$worker->workingOn($job); $worker->workingOn($job);
$worker->doneWorking(); $worker->doneWorking();
@ -170,14 +168,14 @@ class WorkerTest extends TestCase
public function testWorkerRecordsWhatItIsWorkingOn() public function testWorkerRecordsWhatItIsWorkingOn()
{ {
$worker = new \Resque\Worker('jobs'); $worker = new Resque_Worker('jobs');
$worker->setLogger(new \Resque\Log()); $worker->setLogger(new Resque_Log());
$worker->registerWorker(); $worker->registerWorker();
$payload = [ $payload = [
'class' => '\Resque\Test\TestJob' 'class' => 'Test_Job'
]; ];
$job = new \Resque\Job\Job('jobs', $payload); $job = new Resque_Job('jobs', $payload);
$worker->workingOn($job); $worker->workingOn($job);
$job = $worker->job(); $job = $worker->job();
@ -190,17 +188,14 @@ class WorkerTest extends TestCase
public function testWorkerErasesItsStatsWhenShutdown() public function testWorkerErasesItsStatsWhenShutdown()
{ {
\Resque\Resque::enqueue('jobs', '\Resque\Test\TestJob'); Resque::enqueue('jobs', 'Test_Job');
\Resque\Resque::enqueue('jobs', '\Resque\Test\InvalidJob'); Resque::enqueue('jobs', 'Invalid_Job');
$worker = new \Resque\Worker('jobs'); $worker = new Resque_Worker('jobs');
$worker->setLogger(new \Resque\Log()); $worker->setLogger(new Resque_Log());
$worker->work(0); $worker->work(0);
$worker->work(0); $worker->work(0);
// Allow time for async unlink to work
sleep(2);
$this->assertEquals(0, $worker->getStat('processed')); $this->assertEquals(0, $worker->getStat('processed'));
$this->assertEquals(0, $worker->getStat('failed')); $this->assertEquals(0, $worker->getStat('failed'));
} }
@ -208,84 +203,87 @@ class WorkerTest extends TestCase
public function testWorkerCleansUpDeadWorkersOnStartup() public function testWorkerCleansUpDeadWorkersOnStartup()
{ {
// Register a good worker // Register a good worker
$goodWorker = new \Resque\Worker('jobs'); $goodWorker = new Resque_Worker('jobs');
$goodWorker->setLogger(new \Resque\Log()); $goodWorker->setLogger(new Resque_Log());
$goodWorker->registerWorker(); $goodWorker->registerWorker();
$workerId = explode(':', $goodWorker); $workerId = explode(':', $goodWorker);
// Register some bad workers // Register some bad workers
$worker = new \Resque\Worker('jobs'); $worker = new Resque_Worker('jobs');
$worker->setLogger(new \Resque\Log()); $worker->setLogger(new Resque_Log());
$worker->setId($workerId[0] . ':1:jobs'); $worker->setId($workerId[0] . ':1:jobs');
$worker->registerWorker(); $worker->registerWorker();
$worker = new \Resque\Worker(['high', 'low']); $worker = new Resque_Worker(['high', 'low']);
$worker->setLogger(new \Resque\Log()); $worker->setLogger(new Resque_Log());
$worker->setId($workerId[0] . ':2:high,low'); $worker->setId($workerId[0] . ':2:high,low');
$worker->registerWorker(); $worker->registerWorker();
$this->assertEquals(3, count(\Resque\Worker::all())); $this->assertEquals(3, count(Resque_Worker::all()));
$goodWorker->pruneDeadWorkers(); $goodWorker->pruneDeadWorkers();
// There should only be $goodWorker left now // There should only be $goodWorker left now
$this->assertEquals(1, count(\Resque\Worker::all())); $this->assertEquals(1, count(Resque_Worker::all()));
} }
public function testDeadWorkerCleanUpDoesNotCleanUnknownWorkers() public function testDeadWorkerCleanUpDoesNotCleanUnknownWorkers()
{ {
// Register a bad worker on this machine // Register a bad worker on this machine
$worker = new \Resque\Worker('jobs'); $worker = new Resque_Worker('jobs');
$worker->setLogger(new \Resque\Log()); $worker->setLogger(new Resque_Log());
$workerId = explode(':', $worker); $workerId = explode(':', $worker);
$worker->setId($workerId[0] . ':1:jobs'); $worker->setId($workerId[0] . ':1:jobs');
$worker->registerWorker(); $worker->registerWorker();
// Register some other false workers // Register some other false workers
$worker = new \Resque\Worker('jobs'); $worker = new Resque_Worker('jobs');
$worker->setLogger(new \Resque\Log()); $worker->setLogger(new Resque_Log());
$worker->setId('my.other.host:1:jobs'); $worker->setId('my.other.host:1:jobs');
$worker->registerWorker(); $worker->registerWorker();
$this->assertEquals(2, count(\Resque\Worker::all())); $this->assertEquals(2, count(Resque_Worker::all()));
$worker->pruneDeadWorkers(); $worker->pruneDeadWorkers();
// my.other.host should be left // my.other.host should be left
$workers = \Resque\Worker::all(); $workers = Resque_Worker::all();
$this->assertEquals(1, count($workers)); $this->assertEquals(1, count($workers));
$this->assertEquals((string)$worker, (string)$workers[0]); $this->assertEquals((string)$worker, (string)$workers[0]);
} }
public function testWorkerFailsUncompletedJobsOnExit() public function testWorkerFailsUncompletedJobsOnExit()
{ {
$worker = new \Resque\Worker('jobs'); $worker = new Resque_Worker('jobs');
$worker->setLogger(new \Resque\Log()); $worker->setLogger(new Resque_Log());
$worker->registerWorker(); $worker->registerWorker();
$payload = [ $payload = [
'class' => '\Resque\Test\TestJob' 'class' => 'Test_Job'
]; ];
$job = new \Resque\Job\Job('jobs', $payload); $job = new Resque_Job('jobs', $payload);
$worker->workingOn($job); $worker->workingOn($job);
$worker->unregisterWorker(); $worker->unregisterWorker();
$this->assertEquals(1, \Resque\Stat::get('failed')); $this->assertEquals(1, Resque_Stat::get('failed'));
} }
public function testBlockingListPop() public function testBlockingListPop()
{ {
$worker = new \Resque\Worker('jobs'); $this->markTestSkipped("Skip temporarily");
$worker->setLogger(new \Resque\Log()); return;
$worker = new Resque_Worker('jobs');
$worker->setLogger(new Resque_Log());
$worker->registerWorker(); $worker->registerWorker();
\Resque\Resque::enqueue('jobs', '\Resque\Test\TestJob_1'); Resque::enqueue('jobs', 'Test_Job_1');
\Resque\Resque::enqueue('jobs', '\Resque\Test\TestJob_2'); Resque::enqueue('jobs', 'Test_Job_2');
$i = 1; $i = 1;
while ($job = $worker->reserve(true, 2)) { while ($job = $worker->reserve(true, 2)) {
$this->assertEquals('\Resque\Test\TestJob_' . $i, $job->payload['class']); $this->assertEquals('Test_Job_' . $i, $job->payload['class']);
if ($i == 2) { if ($i == 2) {
break; break;

150
test/bootstrap.php Normal file
View file

@ -0,0 +1,150 @@
<?php
/**
* Resque test bootstrap file - sets up a test environment.
*
* @package Resque/Tests
* @author Chris Boulton <chris@bigcommerce.com>
* @license http://www.opensource.org/licenses/mit-license.php
*/
$loader = require __DIR__ . '/../vendor/autoload.php';
$loader->add('Resque_Tests', __DIR__);
define('TEST_MISC', realpath(__DIR__ . '/misc/'));
define('REDIS_CONF', TEST_MISC . '/redis.conf');
// Attempt to start our own redis instance for tesitng.
exec('which redis-server', $output, $returnVar);
if ($returnVar != 0) {
echo "Cannot find redis-server in path. Please make sure redis is installed.\n";
exit(1);
}
exec('cd ' . TEST_MISC . '; redis-server ' . REDIS_CONF, $output, $returnVar);
usleep(500000);
if ($returnVar != 0) {
echo "Cannot start redis-server.\n";
exit(1);
}
// Get redis port from conf
$config = file_get_contents(REDIS_CONF);
if (!preg_match('#^\s*port\s+([0-9]+)#m', $config, $matches)) {
echo "Could not determine redis port from redis.conf";
exit(1);
}
Resque::setBackend('localhost:' . $matches[1]);
// Shutdown
function killRedis($pid)
{
if (getmypid() !== $pid) {
return; // don't kill from a forked worker
}
$config = file_get_contents(REDIS_CONF);
if (!preg_match('#^\s*pidfile\s+([^\s]+)#m', $config, $matches)) {
return;
}
$pidFile = TEST_MISC . '/' . $matches[1];
if (file_exists($pidFile)) {
$pid = trim(file_get_contents($pidFile));
posix_kill((int)$pid, 9);
if (is_file($pidFile)) {
unlink($pidFile);
}
}
// Remove the redis database
if (!preg_match('#^\s*dir\s+([^\s]+)#m', $config, $matches)) {
return;
}
$dir = $matches[1];
if (!preg_match('#^\s*dbfilename\s+([^\s]+)#m', $config, $matches)) {
return;
}
$filename = TEST_MISC . '/' . $dir . '/' . $matches[1];
if (is_file($filename)) {
unlink($filename);
}
}
register_shutdown_function('killRedis', getmypid());
if (function_exists('pcntl_signal')) {
// Override INT and TERM signals, so they do a clean shutdown and also
// clean up redis-server as well.
function sigint()
{
exit;
}
pcntl_signal(SIGINT, 'sigint');
pcntl_signal(SIGTERM, 'sigint');
}
class Test_Job
{
public static $called = false;
public function perform()
{
self::$called = true;
}
}
class Failing_Job_Exception extends Exception
{
}
class Failing_Job
{
public function perform()
{
throw new Failing_Job_Exception('Message!');
}
}
class Test_Job_Without_Perform_Method
{
}
class Test_Job_With_SetUp
{
public static $called = false;
public $args = false;
public function setUp()
{
self::$called = true;
}
public function perform()
{
}
}
class Test_Job_With_TearDown
{
public static $called = false;
public $args = false;
public function perform()
{
}
public function tearDown()
{
self::$called = true;
}
}

8
test/misc/redis.conf Normal file
View file

@ -0,0 +1,8 @@
daemonize yes
pidfile ./redis.pid
port 6379
bind 127.0.0.1
timeout 300
dbfilename dump.rdb
dir ./
loglevel debug

View file

@ -1,110 +0,0 @@
<?php
namespace Resque\Test;
/**
* \Resque\Job\Status tests.
*
* @package Resque/Tests
* @author Daniel Mason <daniel@m2.nz>
* @license http://www.opensource.org/licenses/mit-license.php
*/
class JobStatusTest extends TestCase
{
/**
* @var \Resque\Worker
*/
protected $worker;
public function setUp(): void
{
parent::setUp();
// Register a worker to test with
$this->worker = new \Resque\Worker('jobs');
$this->worker->setLogger(new \Resque\Log());
}
public function testJobStatusCanBeTracked()
{
$token = \Resque\Resque::enqueue('jobs', '\Resque\Test\TestJob', null, true);
$status = new \Resque\Job\Status($token);
$this->assertTrue($status->isTracking());
}
public function testJobStatusIsReturnedViaJobInstance()
{
\Resque\Resque::enqueue('jobs', '\Resque\Test\TestJob', null, true);
$job = \Resque\Job\Job::reserve('jobs');
$this->assertEquals(\Resque\Job\Status::STATUS_WAITING, $job->getStatus());
}
public function testQueuedJobReturnsQueuedStatus()
{
$token = \Resque\Resque::enqueue('jobs', '\Resque\Test\TestJob', null, true);
$status = new \Resque\Job\Status($token);
$this->assertEquals(\Resque\Job\Status::STATUS_WAITING, $status->get());
}
public function testRunningJobReturnsRunningStatus()
{
$token = \Resque\Resque::enqueue('jobs', '\Resque\Test\FailingJob', null, true);
$job = $this->worker->reserve();
$this->worker->workingOn($job);
$status = new \Resque\Job\Status($token);
$this->assertEquals(\Resque\Job\Status::STATUS_RUNNING, $status->get());
}
public function testFailedJobReturnsFailedStatus()
{
$token = \Resque\Resque::enqueue('jobs', '\Resque\Test\FailingJob', null, true);
$this->worker->work(0);
$status = new \Resque\Job\Status($token);
$this->assertEquals(\Resque\Job\Status::STATUS_FAILED, $status->get());
}
public function testCompletedJobReturnsCompletedStatus()
{
$token = \Resque\Resque::enqueue('jobs', '\Resque\Test\TestJob', null, true);
$this->worker->work(0);
$status = new \Resque\Job\Status($token);
$this->assertEquals(\Resque\Job\Status::STATUS_COMPLETE, $status->get());
}
public function testStatusIsNotTrackedWhenToldNotTo()
{
$token = \Resque\Resque::enqueue('jobs', '\Resque\Test\TestJob', null, false);
$status = new \Resque\Job\Status($token);
$this->assertFalse($status->isTracking());
}
public function testStatusTrackingCanBeStopped()
{
\Resque\Job\Status::create('test');
$status = new \Resque\Job\Status('test');
$this->assertEquals(\Resque\Job\Status::STATUS_WAITING, $status->get());
$status->stop();
$this->assertFalse($status->get());
}
public function testRecreatedJobWithTrackingStillTracksStatus()
{
$originalToken = \Resque\Resque::enqueue('jobs', '\Resque\Test\TestJob', null, true);
$job = $this->worker->reserve();
// Mark this job as being worked on to ensure that the new status is still
// waiting.
$this->worker->workingOn($job);
// Now recreate it
$newToken = $job->recreate();
// Make sure we've got a new job returned
$this->assertNotEquals($originalToken, $newToken);
// Now check the status of the new job
$newJob = \Resque\Job\Job::reserve('jobs');
$this->assertEquals(\Resque\Job\Status::STATUS_WAITING, $newJob->getStatus());
}
}

View file

@ -1,431 +0,0 @@
<?php
namespace Resque\Test;
/**
* ResqueJob tests.
*
* @package Resque/Tests
* @author Daniel Mason <daniel@m2.nz>
* @license http://www.opensource.org/licenses/mit-license.php
*/
class JobTest extends TestCase
{
protected $worker;
public function setUp(): void
{
parent::setUp();
// Register a worker to test with
$this->worker = new \Resque\Worker('jobs');
$this->worker->setLogger(new \Resque\Log());
$this->worker->registerWorker();
}
public function testJobCanBeQueued()
{
$this->assertTrue((bool)\Resque\Resque::enqueue('jobs', '\Resque\Test\TestJob'));
}
public function testQeueuedJobCanBeReserved()
{
\Resque\Resque::enqueue('jobs', '\Resque\Test\TestJob');
$job = \Resque\Job\Job::reserve('jobs');
if (is_null($job)) {
$this->fail('Job could not be reserved.');
}
$this->assertEquals('jobs', $job->queue);
$this->assertEquals('\Resque\Test\TestJob', $job->payload['class']);
}
/**
* @expectedException \InvalidArgumentException
*/
public function testObjectArgumentsCannotBePassedToJob()
{
$this->expectException(\InvalidArgumentException::class);
$args = new \stdClass();
$args->test = 'somevalue';
\Resque\Resque::enqueue('jobs', '\Resque\Test\TestJob', $args);
}
public function testQueuedJobReturnsExactSamePassedInArguments()
{
$args = [
'int' => 123,
'numArray' => [
1,
2,
],
'assocArray' => [
'key1' => 'value1',
'key2' => 'value2'
],
];
\Resque\Resque::enqueue('jobs', '\Resque\Test\TestJob', $args);
$job = \Resque\Job\Job::reserve('jobs');
$this->assertEquals($args, $job->getArguments());
}
public function testAfterJobIsReservedItIsRemoved()
{
\Resque\Resque::enqueue('jobs', '\Resque\Test\TestJob');
\Resque\Job\Job::reserve('jobs');
$this->assertNull(\Resque\Job\Job::reserve('jobs'));
}
public function testRecreatedJobMatchesExistingJob()
{
$args = [
'int' => 123,
'numArray' => [
1,
2,
],
'assocArray' => [
'key1' => 'value1',
'key2' => 'value2'
],
];
\Resque\Resque::enqueue('jobs', '\Resque\Test\TestJob', $args);
$job = \Resque\Job\Job::reserve('jobs');
// Now recreate it
$job->recreate();
$newJob = \Resque\Job\Job::reserve('jobs');
$this->assertEquals($job->payload['class'], $newJob->payload['class']);
$this->assertEquals($job->getArguments(), $newJob->getArguments());
}
public function testFailedJobExceptionsAreCaught()
{
$payload = [
'class' => '\Resque\Test\FailingJob',
'args' => null
];
$job = new \Resque\Job\Job('jobs', $payload);
$job->worker = $this->worker;
$this->worker->perform($job);
$this->assertEquals(1, \Resque\Stat::get('failed'));
$this->assertEquals(1, \Resque\Stat::get('failed:' . $this->worker));
}
/**
* @expectedException \Resque\Exception
*/
public function testJobWithoutPerformMethodThrowsException()
{
$this->expectException(\Resque\Exception::class);
\Resque\Resque::enqueue('jobs', '\Resque\Test\TestJob_Without_Perform_Method');
$job = $this->worker->reserve();
$job->worker = $this->worker;
$job->perform();
}
/**
* @expectedException \Resque\Exception
*/
public function testInvalidJobThrowsException()
{
$this->expectException(\Resque\Exception::class);
\Resque\Resque::enqueue('jobs', '\Resque\Test\InvalidJob');
$job = $this->worker->reserve();
$job->worker = $this->worker;
$job->perform();
}
public function testJobWithSetUpCallbackFiresSetUp()
{
$payload = [
'class' => '\Resque\Test\TestJobWithSetUp',
'args' => [
'somevar',
'somevar2',
],
];
$job = new \Resque\Job\Job('jobs', $payload);
$job->perform();
$this->assertTrue(TestJobWithSetUp::$called);
}
public function testJobWithTearDownCallbackFiresTearDown()
{
$payload = [
'class' => '\Resque\Test\TestJobWithTearDown',
'args' => [
'somevar',
'somevar2',
],
];
$job = new \Resque\Job\Job('jobs', $payload);
$job->perform();
$this->assertTrue(TestJobWithTearDown::$called);
}
public function testNamespaceNaming()
{
$fixture = [
['test' => 'more:than:one:with:', 'assertValue' => 'more:than:one:with:'],
['test' => 'more:than:one:without', 'assertValue' => 'more:than:one:without:'],
['test' => 'resque', 'assertValue' => 'resque:'],
['test' => 'resque:', 'assertValue' => 'resque:'],
];
foreach ($fixture as $item) {
\Resque\Redis::prefix($item['test']);
$this->assertEquals(\Resque\Redis::getPrefix(), $item['assertValue']);
}
}
public function testJobWithNamespace()
{
\Resque\Redis::prefix('php');
$queue = 'jobs';
$payload = ['another_value'];
\Resque\Resque::enqueue($queue, '\Resque\Test\TestJobWithTearDown', $payload);
$this->assertEquals(\Resque\Resque::queues(), ['jobs']);
$this->assertEquals(\Resque\Resque::size($queue), 1);
\Resque\Redis::prefix('resque');
$this->assertEquals(\Resque\Resque::size($queue), 0);
}
public function testDequeueAll()
{
$queue = 'jobs';
\Resque\Resque::enqueue($queue, '\Resque\Test\TestJobDequeue');
\Resque\Resque::enqueue($queue, '\Resque\Test\TestJobDequeue');
$this->assertEquals(\Resque\Resque::size($queue), 2);
$this->assertEquals(\Resque\Resque::dequeue($queue), 2);
$this->assertEquals(\Resque\Resque::size($queue), 0);
}
public function testDequeueMakeSureNotDeleteOthers()
{
$queue = 'jobs';
\Resque\Resque::enqueue($queue, '\Resque\Test\TestJobDequeue');
\Resque\Resque::enqueue($queue, '\Resque\Test\TestJobDequeue');
$other_queue = 'other_jobs';
\Resque\Resque::enqueue($other_queue, '\Resque\Test\TestJobDequeue');
\Resque\Resque::enqueue($other_queue, '\Resque\Test\TestJobDequeue');
$this->assertEquals(\Resque\Resque::size($queue), 2);
$this->assertEquals(\Resque\Resque::size($other_queue), 2);
$this->assertEquals(\Resque\Resque::dequeue($queue), 2);
$this->assertEquals(\Resque\Resque::size($queue), 0);
$this->assertEquals(\Resque\Resque::size($other_queue), 2);
}
public function testDequeueSpecificItem()
{
$queue = 'jobs';
\Resque\Resque::enqueue($queue, '\Resque\Test\TestJobDequeue1');
\Resque\Resque::enqueue($queue, '\Resque\Test\TestJobDequeue2');
$this->assertEquals(\Resque\Resque::size($queue), 2);
$test = ['\Resque\Test\TestJobDequeue2'];
$this->assertEquals(\Resque\Resque::dequeue($queue, $test), 1);
$this->assertEquals(\Resque\Resque::size($queue), 1);
}
public function testDequeueSpecificMultipleItems()
{
$queue = 'jobs';
\Resque\Resque::enqueue($queue, '\Resque\Test\TestJob_Dequeue1');
\Resque\Resque::enqueue($queue, '\Resque\Test\TestJob_Dequeue2');
\Resque\Resque::enqueue($queue, '\Resque\Test\TestJob_Dequeue3');
$this->assertEquals(\Resque\Resque::size($queue), 3);
$test = ['\Resque\Test\TestJob_Dequeue2', '\Resque\Test\TestJob_Dequeue3'];
$this->assertEquals(\Resque\Resque::dequeue($queue, $test), 2);
$this->assertEquals(\Resque\Resque::size($queue), 1);
}
public function testDequeueNonExistingItem()
{
$queue = 'jobs';
\Resque\Resque::enqueue($queue, '\Resque\Test\TestJob_Dequeue1');
\Resque\Resque::enqueue($queue, '\Resque\Test\TestJob_Dequeue2');
\Resque\Resque::enqueue($queue, '\Resque\Test\TestJob_Dequeue3');
$this->assertEquals(\Resque\Resque::size($queue), 3);
$test = ['\Resque\Test\TestJob_Dequeue4'];
$this->assertEquals(\Resque\Resque::dequeue($queue, $test), 0);
$this->assertEquals(\Resque\Resque::size($queue), 3);
}
public function testDequeueNonExistingItem2()
{
$queue = 'jobs';
\Resque\Resque::enqueue($queue, '\Resque\Test\TestJob_Dequeue1');
\Resque\Resque::enqueue($queue, '\Resque\Test\TestJob_Dequeue2');
\Resque\Resque::enqueue($queue, '\Resque\Test\TestJob_Dequeue3');
$this->assertEquals(\Resque\Resque::size($queue), 3);
$test = ['\Resque\Test\TestJob_Dequeue4', '\Resque\Test\TestJob_Dequeue1'];
$this->assertEquals(\Resque\Resque::dequeue($queue, $test), 1);
$this->assertEquals(\Resque\Resque::size($queue), 2);
}
public function testDequeueItemID()
{
$queue = 'jobs';
\Resque\Resque::enqueue($queue, '\Resque\Test\TestJob_Dequeue');
$qid = \Resque\Resque::enqueue($queue, '\Resque\Test\TestJob_Dequeue');
$this->assertEquals(\Resque\Resque::size($queue), 2);
$test = ['\Resque\Test\TestJob_Dequeue' => $qid];
$this->assertEquals(\Resque\Resque::dequeue($queue, $test), 1);
$this->assertEquals(\Resque\Resque::size($queue), 1);
}
public function testDequeueWrongItemID()
{
$queue = 'jobs';
\Resque\Resque::enqueue($queue, '\Resque\Test\TestJob_Dequeue');
$qid = \Resque\Resque::enqueue($queue, '\Resque\Test\TestJob_Dequeue');
$this->assertEquals(\Resque\Resque::size($queue), 2);
#qid right but class name is wrong
$test = ['\Resque\Test\TestJob_Dequeue1' => $qid];
$this->assertEquals(\Resque\Resque::dequeue($queue, $test), 0);
$this->assertEquals(\Resque\Resque::size($queue), 2);
}
public function testDequeueWrongItemID2()
{
$queue = 'jobs';
\Resque\Resque::enqueue($queue, '\Resque\Test\TestJob_Dequeue');
\Resque\Resque::enqueue($queue, '\Resque\Test\TestJob_Dequeue');
$this->assertEquals(\Resque\Resque::size($queue), 2);
$test = ['\Resque\Test\TestJob_Dequeue' => 'r4nD0mH4sh3dId'];
$this->assertEquals(\Resque\Resque::dequeue($queue, $test), 0);
$this->assertEquals(\Resque\Resque::size($queue), 2);
}
public function testDequeueItemWithArg()
{
$queue = 'jobs';
$arg = ['foo' => 1, 'bar' => 2];
\Resque\Resque::enqueue($queue, '\Resque\Test\TestJobDequeue9');
\Resque\Resque::enqueue($queue, '\Resque\Test\TestJobDequeue9', $arg);
$this->assertEquals(\Resque\Resque::size($queue), 2);
$test = ['\Resque\Test\TestJobDequeue9' => $arg];
$this->assertEquals(\Resque\Resque::dequeue($queue, $test), 1);
#$this->assertEquals(\Resque\Resque::size($queue), 1);
}
public function testDequeueSeveralItemsWithArgs()
{
// GIVEN
$queue = 'jobs';
$args = ['foo' => 1, 'bar' => 10];
$removeArgs = ['foo' => 1, 'bar' => 2];
\Resque\Resque::enqueue($queue, '\Resque\Test\TestJobDequeue9', $args);
\Resque\Resque::enqueue($queue, '\Resque\Test\TestJobDequeue9', $removeArgs);
\Resque\Resque::enqueue($queue, '\Resque\Test\TestJobDequeue9', $removeArgs);
$this->assertEquals(\Resque\Resque::size($queue), 3, "Failed to add 3 items.");
// WHEN
$test = ['\Resque\Test\TestJobDequeue9' => $removeArgs];
$removedItems = \Resque\Resque::dequeue($queue, $test);
// THEN
$this->assertEquals($removedItems, 2);
$this->assertEquals(\Resque\Resque::size($queue), 1);
$item = \Resque\Resque::pop($queue);
$this->assertIsArray($item['args']);
$this->assertEquals(10, $item['args'][0]['bar'], 'Wrong items were dequeued from queue!');
}
public function testDequeueItemWithUnorderedArg()
{
$queue = 'jobs';
$arg = ['foo' => 1, 'bar' => 2];
$arg2 = ['bar' => 2, 'foo' => 1];
\Resque\Resque::enqueue($queue, '\Resque\Test\TestJobDequeue');
\Resque\Resque::enqueue($queue, '\Resque\Test\TestJobDequeue', $arg);
$this->assertEquals(\Resque\Resque::size($queue), 2);
$test = ['\Resque\Test\TestJobDequeue' => $arg2];
$this->assertEquals(\Resque\Resque::dequeue($queue, $test), 1);
$this->assertEquals(\Resque\Resque::size($queue), 1);
}
public function testDequeueItemWithiWrongArg()
{
$queue = 'jobs';
$arg = ['foo' => 1, 'bar' => 2];
$arg2 = ['foo' => 2, 'bar' => 3];
\Resque\Resque::enqueue($queue, '\Resque\Test\TestJobDequeue');
\Resque\Resque::enqueue($queue, '\Resque\Test\TestJobDequeue', $arg);
$this->assertEquals(\Resque\Resque::size($queue), 2);
$test = ['\Resque\Test\TestJobDequeue' => $arg2];
$this->assertEquals(\Resque\Resque::dequeue($queue, $test), 0);
$this->assertEquals(\Resque\Resque::size($queue), 2);
}
public function testUseDefaultFactoryToGetJobInstance()
{
$payload = [
'class' => '\Resque\Test\SomeJobClass',
'args' => null
];
$job = new \Resque\Job\Job('jobs', $payload);
$instance = $job->getInstance();
$this->assertInstanceOf('\Resque\Test\SomeJobClass', $instance);
}
public function testUseFactoryToGetJobInstance()
{
$payload = [
'class' => 'SomeJobClass',
'args' => [[]]
];
$job = new \Resque\Job\Job('jobs', $payload);
$factory = new Some_Stub_Factory();
$job->setJobFactory($factory);
$instance = $job->getInstance();
$this->assertInstanceOf('\Resque\Job\JobInterface', $instance);
}
}
class SomeJobClass implements \Resque\Job\JobInterface
{
public static $called = false;
public $args = false;
public $queue;
public $job;
/**
* @return bool
*/
public function perform()
{
return true;
}
}
class Some_Stub_Factory implements \Resque\Job\FactoryInterface
{
public static $called = false;
public $args = false;
public $queue;
public $job;
/**
* @param $className
* @param array $args
* @param $queue
* @return \Resque\Job\JobInterface
*/
public function create($className, $args, $queue)
{
return new SomeJobClass();
}
}

View file

@ -1,102 +0,0 @@
<?php
namespace Resque\Test;
/**
* Resque test bootstrap file - sets up a test environment.
*
* @package Resque/Tests
* @author Daniel Mason <daniel@m2.nz>
* @license http://www.opensource.org/licenses/mit-license.php
*/
$loader = require __DIR__ . '/../vendor/autoload.php';
# Redis configuration
global $redisTestServer;
$redisTestServer = getenv("REDIS_SERVER") ?: "redis";
\Resque\Resque::setBackend($redisTestServer);
# Check Redis is accessable locally
try {
$redisTest = new \Resque\Redis($redisTestServer);
} catch (\Exception $e) {
throw new \Exception("Unable to connect to redis. Please check there is a redis-server running.");
}
$redisTest = null;
# Cleanup forked workers cleanly
if (function_exists('pcntl_signal')) {
pcntl_signal(SIGINT, function() { exit; });
pcntl_signal(SIGTERM, function() { exit; });
}
# Bootstrap it
class TestJob
{
public static $called = false;
public $args = false;
public $queue;
public $job;
public function perform()
{
self::$called = true;
}
}
class FailingJobException extends \Exception
{
}
class FailingJob
{
public static $called = false;
public $args = false;
public $queue;
public $job;
public function perform()
{
throw new FailingJobException('Message!');
}
}
class TestJobWithoutPerformMethod
{
}
class TestJobWithSetUp
{
public static $called = false;
public $args = false;
public $queue;
public $job;
public function setUp()
{
self::$called = true;
}
public function perform()
{
}
}
class TestJobWithTearDown
{
public static $called = false;
public $args = false;
public $queue;
public $job;
public function perform()
{
}
public function tearDown()
{
self::$called = true;
}
}