diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml deleted file mode 100644 index b270598..0000000 --- a/.github/workflows/ci.yml +++ /dev/null @@ -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 diff --git a/.gitignore b/.gitignore index aa30d8b..a793d95 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ vendor/ -.phpunit.result.cache \ No newline at end of file +*.swp +phpunit.xml diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml deleted file mode 100644 index fe02d9b..0000000 --- a/.gitlab-ci.yml +++ /dev/null @@ -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 \ No newline at end of file diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..91c26ad --- /dev/null +++ b/.travis.yml @@ -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 diff --git a/CHANGELOG.md b/CHANGELOG.md index 276f6e3..d69f841 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,83 +1,5 @@ -# 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) -- Updated README to include supervisor configuration. -- Change logfile date format to `%Y-%m-%d %T`. -- Added return types to more functions. - ## 1.4.2 (2018-05-30) - Reimplemented credis due to issues with Redis: Connection Closed. -- Updated Docs. ## 1.4.1 (2018-05-29) - Updated travis builds to run on PHP 7.0, 7.1 and 7.2. @@ -91,6 +13,7 @@ - Replaced credis in favour of phpredis. - Reformatted codebase to be PSR2 compliant. + ## 1.3 (2013) **Note:** This release introduces backwards incompatible changes with all previous versions of php-resque. Please see below for details. @@ -150,7 +73,7 @@ Changes by iskandar introduce improved support for using DSNs to connect to Redi * Pass queue name to afterEvent callback * Only declare RedisException if it doesn't already exist (Matt Heath) * 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) * General tidy up of comments and files/folders diff --git a/HOWITWORKS.md b/HOWITWORKS.md index 7168926..ec85fa3 100644 --- a/HOWITWORKS.md +++ b/HOWITWORKS.md @@ -14,9 +14,9 @@ What happens when you call `Resque::enqueue()`? 4. `Resque_Job::create()` pushes the job to the requested queue (first argument) 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 -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 value, then returns control to `Resque_Job::create()` 7. `Resque_Job::create()` returns control to `Resque::enqueue()`, with the job @@ -85,15 +85,15 @@ How do the workers process the queues? * Worker 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 - a `Resque\Job\DirtyExitException` as its only argument. + a `Resque_Job_DirtyExitException` as its only argument. 3. `Resque_Job->fail()` triggers an `onFailure` event 4. `Resque_Job->fail()` updates the job status from `RUNNING` to `FAILED` 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 6. `Resque_Failure::create()` creates a new object of whatever type has 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 in the `failed` queue 7. `Resque_Job->fail()` increments two failure counters in Redis: one for diff --git a/README.md b/README.md index c2d7234..32e5db7 100644 --- a/README.md +++ b/README.md @@ -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 @@ -34,15 +34,9 @@ not exit with a status code as 0 * Has built in support for `setUp` and `tearDown` methods, called pre and post jobs -On top of the original fork (chrisboulton/php-resque) I have added: - -* Custom log levels -* PHP7.0+ compatibility - - ## Requirements ## -* PHP 8.1+ +* PHP 7.0+ (May work with 5.6+, Untested) * phpredis * Redis 2.2+ @@ -53,9 +47,19 @@ Composer package inside your project. If you're not familiar with Composer, please see . -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) ```sh @@ -70,11 +74,12 @@ Jobs are queued as follows: ```php // Required if redis is located elsewhere -Resque::setBackend('redis:6379'); +Resque::setBackend('localhost:6379'); -$args = ['name' => 'TestName']; - -Resque::enqueue('default', '\App\MyJobClass', $args); +$args = array( + 'name' => 'TestName' + ); +Resque::enqueue('default', 'My_Job', $args); ``` ### Defining Jobs ### @@ -82,9 +87,7 @@ Resque::enqueue('default', '\App\MyJobClass', $args); Each job should be in its own class, and include a `perform` method. ```php -namespace \App; - -class MyJobClass +class My_Job { public function perform() { @@ -107,9 +110,7 @@ The `tearDown` method, if defined, will be called after the job finishes. ```php -namespace App; - -class MyJobClass +class My_Job { public function setUp() { @@ -133,17 +134,17 @@ class MyJobClass This method can be used to conveniently remove a job from a queue. ```php -// Removes job class '\App\MyJobClass' of queue 'default' -Resque::dequeue('default', ['\App\MyJobClass']); +// Removes job class 'My_Job' of queue 'default' +Resque::dequeue('default', ['My_Job']); -// Removes job class '\App\MyJobClass' with Job ID '087df5819a790ac666c9608e2234b21e' of queue 'default' -Resque::dequeue('default', ['\App\MyJobClass' => '087df5819a790ac666c9608e2234b21e']); +// Removes job class 'My_Job' with Job ID '087df5819a790ac666c9608e2234b21e' of queue 'default' +Resque::dequeue('default', ['My_Job' => '087df5819a790ac666c9608e2234b21e']); -// Removes job class '\App\MyJobClass' with arguments of queue 'default' -Resque::dequeue('default', ['\App\MyJobClass' => ['foo' => 1, 'bar' => 2]]); +// Removes job class 'My_Job' with arguments of queue 'default' +Resque::dequeue('default', ['My_Job' => array('foo' => 1, 'bar' => 2)]); // 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. @@ -164,7 +165,7 @@ To track the status of a job, pass `true` as the fourth argument to returned: ```php -$token = Resque::enqueue('default', '\App\MyJobClass', $args, true); +$token = Resque::enqueue('default', 'My_Job', $args, true); echo $token; ``` @@ -344,7 +345,7 @@ Resque_Event::listen('eventName', [callback]); * A string with the name of a function * An array containing an object and method to call * An array containing an object and a static method to call -* A closure +* A closure (PHP 5.3+) Events may pass arguments (documented below), so your callback should accept these arguments. @@ -361,6 +362,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 responsibility to register listeners. +A sample plugin is included in the `extras` directory. + ### Events ### #### beforeFirstFork #### @@ -430,30 +433,6 @@ Called after a job has been queued using the `Resque::enqueue` method. Arguments * Queue - string containing the name of the queue the job was added to * ID - string containing the new token of the enqueued job -## Supervisor Configuration ## - -You may like to run php-resque on a supervisor task to manage the processes. -The following is a default config that can be modified to suit. - -```sh -[program:resque-dev] -directory=/var/www # Project root -command=php vendor/bin/resque -numprocs=2 # Change this value for more threads -environment=LOGLEVEL=NOTICE,QUEUE='*',BLOCKING=1,COUNT=1,APP_INCLUDE='includes/autoload.php',REDIS_BACKEND=127.0.0.1,REDIS_BACKEND_DB=0 -redirect_stderr=true # Output stderr to logfile -stdout_logfile=/var/log/resque.log -autostart=true -autorestart=true -stopsignal=QUIT -process_name = %(program_name)s_%(process_num)02d -``` - -Issues: -- Restarting worker doesn't always make it use updated code, I find on a dev-environment issuing -the following command works well to restart everything. -`sudo /etc/init.d/supervisor force-stop && sleep 1 && sudo /etc/init.d/supervisor restart` - ## Step-By-Step ## For a more in-depth look at what php-resque does under the hood (without @@ -462,7 +441,7 @@ needing to directly examine the code), have a look at `HOWITWORKS.md`. ## Contributors ## ### Current Maintainers ### -* @idanoo +* @iDanoo ### Past Maintainer / Forked From ### diff --git a/bin/resque b/bin/resque index 073f05a..5867c60 100755 --- a/bin/resque +++ b/bin/resque @@ -9,6 +9,7 @@ $files = [ __DIR__ . '/../vendor/autoload.php', ]; +$found = false; foreach ($files as $file) { if (file_exists($file)) { require_once $file; @@ -24,7 +25,6 @@ if (!class_exists('Composer\Autoload\ClassLoader', false)) { ); } -// Set which queues to monitor '*' $QUEUE = getenv('QUEUE'); if (empty($QUEUE)) { die("Set QUEUE env var containing the list of queues to work.\n"); @@ -38,26 +38,21 @@ if (empty($QUEUE)) { */ $REDIS_BACKEND = getenv('REDIS_BACKEND'); -/** - * REDIS_BACKEND_DB overrides default Redis DB - */ +// A redis database number $REDIS_BACKEND_DB = getenv('REDIS_BACKEND_DB'); if (!empty($REDIS_BACKEND)) { - if (empty($REDIS_BACKEND_DB)) { - \Resque\Resque::setBackend($REDIS_BACKEND); - } else { - \Resque\Resque::setBackend($REDIS_BACKEND, $REDIS_BACKEND_DB); - } + if (empty($REDIS_BACKEND_DB)) + Resque::setBackend($REDIS_BACKEND); + else + Resque::setBackend($REDIS_BACKEND, $REDIS_BACKEND_DB); } -// Set Logging level $logLevel = false; $LOGGING = getenv('LOGLEVEL'); -if (!empty($LOGGING)) { +if (!empty($LOGGING) ) { $logLevel = $LOGGING; } -// Bootstrap file $APP_INCLUDE = getenv('APP_INCLUDE'); if ($APP_INCLUDE) { if (!file_exists($APP_INCLUDE)) { @@ -70,45 +65,41 @@ if ($APP_INCLUDE) { // See if the APP_INCLUDE containes a logger object, // If none exists, fallback to internal 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; -// Interval to check for jobs $interval = 5; $INTERVAL = getenv('INTERVAL'); if (!empty($INTERVAL)) { $interval = $INTERVAL; } -// Sets worker count $count = 1; $COUNT = getenv('COUNT'); if (!empty($COUNT) && $COUNT > 1) { $count = $COUNT; } -// Determines redis key prefix $PREFIX = getenv('PREFIX'); if (!empty($PREFIX)) { - $logger->log(\Psr\Log\LogLevel::INFO, 'Prefix set to {prefix}', ['prefix' => $PREFIX]); - \Resque\Redis::prefix($PREFIX); + $logger->log(Psr\Log\LogLevel::INFO, 'Prefix set to {prefix}', ['prefix' => $PREFIX]); + Resque_Redis::prefix($PREFIX); } if ($count > 1) { for ($i = 0; $i < $count; ++$i) { - $pid = \Resque\Resque::fork(); + $pid = Resque::fork(); 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(); } elseif (!$pid) { // Child, start the worker $queues = explode(',', $QUEUE); - $worker = new \Resque\Worker($queues); + $worker = new Resque_Worker($queues); $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); break; } @@ -116,7 +107,7 @@ if ($count > 1) { } else { // Start a single worker $queues = explode(',', $QUEUE); - $worker = new \Resque\Worker($queues); + $worker = new Resque_Worker($queues); $worker->setLogger($logger); $PIDFILE = getenv('PIDFILE'); @@ -125,6 +116,6 @@ if ($count > 1) { 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); } diff --git a/build.xml b/build.xml new file mode 100644 index 0000000..b51c486 --- /dev/null +++ b/build.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/composer.json b/composer.json index 15199f0..045bb40 100644 --- a/composer.json +++ b/composer.json @@ -1,13 +1,10 @@ { "name": "idanoo/php-resque", + "version": "1.4.2", "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.", - "keywords": ["job", "background", "redis", "resque", "php"], - "homepage": "https://github.com/idanoo/php-resque", + "keywords": ["job", "background", "redis", "resque"], + "homepage": "http://www.github.com/iDanoo/php-resque/", "license": "MIT", "authors": [ { @@ -16,36 +13,24 @@ } ], "require": { - "php": ">=8.1", - "psr/log": "^1.1 || ^2.0 || ^3.0", - "colinmollenhour/credis": "^1.14.0" + "php": "^7.0", + "ext-pcntl": "*", + "ext-redis": "*", + "psr/log": "~1.0", + "colinmollenhour/credis": "^1.10" + }, + "suggest": { + "ext-proctitle": "Allows php-resque to rename the title of UNIX processes to show the status of a worker." }, "require-dev": { - "phpunit/phpunit": "^9", - "squizlabs/php_codesniffer": "3.*", - "phpcompatibility/php-compatibility": "^9.3", - "dealerdirect/phpcodesniffer-composer-installer": "^1.0" + "phpunit/phpunit": "^6" }, "bin": [ "bin/resque" ], "autoload": { - "psr-4": { - "Resque\\": "src/Resque" - } - }, - "autoload-dev": { - "psr-4": { - "Resque\\Test\\": "tests/Resque/Tests" - } - }, - "support": { - "issues": "https://github.com/idanoo/php-resque/issues", - "source": "https://github.com/idanoo/php-resque" - }, - "config": { - "allow-plugins": { - "dealerdirect/phpcodesniffer-composer-installer": true + "psr-0": { + "Resque": "lib" } } } diff --git a/composer.lock b/composer.lock deleted file mode 100644 index bb2aed1..0000000 --- a/composer.lock +++ /dev/null @@ -1,2092 +0,0 @@ -{ - "_readme": [ - "This file locks the dependencies of your project to a known state", - "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", - "This file is @generated automatically" - ], - "content-hash": "d8e5313006d5c73b54ee6a410b1ad016", - "packages": [ - { - "name": "colinmollenhour/credis", - "version": "v1.17.0", - "source": { - "type": "git", - "url": "https://github.com/colinmollenhour/credis.git", - "reference": "f4930b426f6b1238b687a1ffe6ee5af7f835b40a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/colinmollenhour/credis/zipball/f4930b426f6b1238b687a1ffe6ee5af7f835b40a", - "reference": "f4930b426f6b1238b687a1ffe6ee5af7f835b40a", - "shasum": "" - }, - "require": { - "php": ">=7.4.0" - }, - "suggest": { - "ext-redis": "Improved performance for communicating with redis" - }, - "type": "library", - "autoload": { - "classmap": [ - "Client.php", - "Cluster.php", - "Sentinel.php", - "Module.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Colin Mollenhour", - "email": "colin@mollenhour.com" - } - ], - "description": "Credis is a lightweight interface to the Redis key-value store which wraps the phpredis library when available for better performance.", - "homepage": "https://github.com/colinmollenhour/credis", - "support": { - "issues": "https://github.com/colinmollenhour/credis/issues", - "source": "https://github.com/colinmollenhour/credis/tree/v1.17.0" - }, - "time": "2025-02-10T18:58:46+00:00" - }, - { - "name": "psr/log", - "version": "3.0.2", - "source": { - "type": "git", - "url": "https://github.com/php-fig/log.git", - "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", - "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", - "shasum": "" - }, - "require": { - "php": ">=8.0.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Log\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "description": "Common interface for logging libraries", - "homepage": "https://github.com/php-fig/log", - "keywords": [ - "log", - "psr", - "psr-3" - ], - "support": { - "source": "https://github.com/php-fig/log/tree/3.0.2" - }, - "time": "2024-09-11T13:17:53+00:00" - } - ], - "packages-dev": [ - { - "name": "dealerdirect/phpcodesniffer-composer-installer", - "version": "v1.0.0", - "source": { - "type": "git", - "url": "https://github.com/PHPCSStandards/composer-installer.git", - "reference": "4be43904336affa5c2f70744a348312336afd0da" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/PHPCSStandards/composer-installer/zipball/4be43904336affa5c2f70744a348312336afd0da", - "reference": "4be43904336affa5c2f70744a348312336afd0da", - "shasum": "" - }, - "require": { - "composer-plugin-api": "^1.0 || ^2.0", - "php": ">=5.4", - "squizlabs/php_codesniffer": "^2.0 || ^3.1.0 || ^4.0" - }, - "require-dev": { - "composer/composer": "*", - "ext-json": "*", - "ext-zip": "*", - "php-parallel-lint/php-parallel-lint": "^1.3.1", - "phpcompatibility/php-compatibility": "^9.0", - "yoast/phpunit-polyfills": "^1.0" - }, - "type": "composer-plugin", - "extra": { - "class": "PHPCSStandards\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Plugin" - }, - "autoload": { - "psr-4": { - "PHPCSStandards\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Franck Nijhof", - "email": "franck.nijhof@dealerdirect.com", - "homepage": "http://www.frenck.nl", - "role": "Developer / IT Manager" - }, - { - "name": "Contributors", - "homepage": "https://github.com/PHPCSStandards/composer-installer/graphs/contributors" - } - ], - "description": "PHP_CodeSniffer Standards Composer Installer Plugin", - "homepage": "http://www.dealerdirect.com", - "keywords": [ - "PHPCodeSniffer", - "PHP_CodeSniffer", - "code quality", - "codesniffer", - "composer", - "installer", - "phpcbf", - "phpcs", - "plugin", - "qa", - "quality", - "standard", - "standards", - "style guide", - "stylecheck", - "tests" - ], - "support": { - "issues": "https://github.com/PHPCSStandards/composer-installer/issues", - "source": "https://github.com/PHPCSStandards/composer-installer" - }, - "time": "2023-01-05T11:28:13+00:00" - }, - { - "name": "doctrine/instantiator", - "version": "2.0.0", - "source": { - "type": "git", - "url": "https://github.com/doctrine/instantiator.git", - "reference": "c6222283fa3f4ac679f8b9ced9a4e23f163e80d0" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/c6222283fa3f4ac679f8b9ced9a4e23f163e80d0", - "reference": "c6222283fa3f4ac679f8b9ced9a4e23f163e80d0", - "shasum": "" - }, - "require": { - "php": "^8.1" - }, - "require-dev": { - "doctrine/coding-standard": "^11", - "ext-pdo": "*", - "ext-phar": "*", - "phpbench/phpbench": "^1.2", - "phpstan/phpstan": "^1.9.4", - "phpstan/phpstan-phpunit": "^1.3", - "phpunit/phpunit": "^9.5.27", - "vimeo/psalm": "^5.4" - }, - "type": "library", - "autoload": { - "psr-4": { - "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com", - "homepage": "https://ocramius.github.io/" - } - ], - "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", - "homepage": "https://www.doctrine-project.org/projects/instantiator.html", - "keywords": [ - "constructor", - "instantiate" - ], - "support": { - "issues": "https://github.com/doctrine/instantiator/issues", - "source": "https://github.com/doctrine/instantiator/tree/2.0.0" - }, - "funding": [ - { - "url": "https://www.doctrine-project.org/sponsorship.html", - "type": "custom" - }, - { - "url": "https://www.patreon.com/phpdoctrine", - "type": "patreon" - }, - { - "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finstantiator", - "type": "tidelift" - } - ], - "time": "2022-12-30T00:23:10+00:00" - }, - { - "name": "myclabs/deep-copy", - "version": "1.13.1", - "source": { - "type": "git", - "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "1720ddd719e16cf0db4eb1c6eca108031636d46c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/1720ddd719e16cf0db4eb1c6eca108031636d46c", - "reference": "1720ddd719e16cf0db4eb1c6eca108031636d46c", - "shasum": "" - }, - "require": { - "php": "^7.1 || ^8.0" - }, - "conflict": { - "doctrine/collections": "<1.6.8", - "doctrine/common": "<2.13.3 || >=3 <3.2.2" - }, - "require-dev": { - "doctrine/collections": "^1.6.8", - "doctrine/common": "^2.13.3 || ^3.2.2", - "phpspec/prophecy": "^1.10", - "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" - }, - "type": "library", - "autoload": { - "files": [ - "src/DeepCopy/deep_copy.php" - ], - "psr-4": { - "DeepCopy\\": "src/DeepCopy/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "Create deep copies (clones) of your objects", - "keywords": [ - "clone", - "copy", - "duplicate", - "object", - "object graph" - ], - "support": { - "issues": "https://github.com/myclabs/DeepCopy/issues", - "source": "https://github.com/myclabs/DeepCopy/tree/1.13.1" - }, - "funding": [ - { - "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", - "type": "tidelift" - } - ], - "time": "2025-04-29T12:36:36+00:00" - }, - { - "name": "nikic/php-parser", - "version": "v5.5.0", - "source": { - "type": "git", - "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "ae59794362fe85e051a58ad36b289443f57be7a9" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/ae59794362fe85e051a58ad36b289443f57be7a9", - "reference": "ae59794362fe85e051a58ad36b289443f57be7a9", - "shasum": "" - }, - "require": { - "ext-ctype": "*", - "ext-json": "*", - "ext-tokenizer": "*", - "php": ">=7.4" - }, - "require-dev": { - "ircmaxell/php-yacc": "^0.0.7", - "phpunit/phpunit": "^9.0" - }, - "bin": [ - "bin/php-parse" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.0-dev" - } - }, - "autoload": { - "psr-4": { - "PhpParser\\": "lib/PhpParser" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Nikita Popov" - } - ], - "description": "A PHP parser written in PHP", - "keywords": [ - "parser", - "php" - ], - "support": { - "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v5.5.0" - }, - "time": "2025-05-31T08:24:38+00:00" - }, - { - "name": "phar-io/manifest", - "version": "2.0.4", - "source": { - "type": "git", - "url": "https://github.com/phar-io/manifest.git", - "reference": "54750ef60c58e43759730615a392c31c80e23176" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phar-io/manifest/zipball/54750ef60c58e43759730615a392c31c80e23176", - "reference": "54750ef60c58e43759730615a392c31c80e23176", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-libxml": "*", - "ext-phar": "*", - "ext-xmlwriter": "*", - "phar-io/version": "^3.0.1", - "php": "^7.2 || ^8.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" - }, - { - "name": "Sebastian Heuer", - "email": "sebastian@phpeople.de", - "role": "Developer" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "Developer" - } - ], - "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", - "support": { - "issues": "https://github.com/phar-io/manifest/issues", - "source": "https://github.com/phar-io/manifest/tree/2.0.4" - }, - "funding": [ - { - "url": "https://github.com/theseer", - "type": "github" - } - ], - "time": "2024-03-03T12:33:53+00:00" - }, - { - "name": "phar-io/version", - "version": "3.2.1", - "source": { - "type": "git", - "url": "https://github.com/phar-io/version.git", - "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74", - "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0" - }, - "type": "library", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" - }, - { - "name": "Sebastian Heuer", - "email": "sebastian@phpeople.de", - "role": "Developer" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "Developer" - } - ], - "description": "Library for handling version information and constraints", - "support": { - "issues": "https://github.com/phar-io/version/issues", - "source": "https://github.com/phar-io/version/tree/3.2.1" - }, - "time": "2022-02-21T01:04:05+00:00" - }, - { - "name": "phpcompatibility/php-compatibility", - "version": "9.3.5", - "source": { - "type": "git", - "url": "https://github.com/PHPCompatibility/PHPCompatibility.git", - "reference": "9fb324479acf6f39452e0655d2429cc0d3914243" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibility/zipball/9fb324479acf6f39452e0655d2429cc0d3914243", - "reference": "9fb324479acf6f39452e0655d2429cc0d3914243", - "shasum": "" - }, - "require": { - "php": ">=5.3", - "squizlabs/php_codesniffer": "^2.3 || ^3.0.2" - }, - "conflict": { - "squizlabs/php_codesniffer": "2.6.2" - }, - "require-dev": { - "phpunit/phpunit": "~4.5 || ^5.0 || ^6.0 || ^7.0" - }, - "suggest": { - "dealerdirect/phpcodesniffer-composer-installer": "^0.5 || This Composer plugin will sort out the PHPCS 'installed_paths' automatically.", - "roave/security-advisories": "dev-master || Helps prevent installing dependencies with known security issues." - }, - "type": "phpcodesniffer-standard", - "notification-url": "https://packagist.org/downloads/", - "license": [ - "LGPL-3.0-or-later" - ], - "authors": [ - { - "name": "Wim Godden", - "homepage": "https://github.com/wimg", - "role": "lead" - }, - { - "name": "Juliette Reinders Folmer", - "homepage": "https://github.com/jrfnl", - "role": "lead" - }, - { - "name": "Contributors", - "homepage": "https://github.com/PHPCompatibility/PHPCompatibility/graphs/contributors" - } - ], - "description": "A set of sniffs for PHP_CodeSniffer that checks for PHP cross-version compatibility.", - "homepage": "http://techblog.wimgodden.be/tag/codesniffer/", - "keywords": [ - "compatibility", - "phpcs", - "standards" - ], - "support": { - "issues": "https://github.com/PHPCompatibility/PHPCompatibility/issues", - "source": "https://github.com/PHPCompatibility/PHPCompatibility" - }, - "time": "2019-12-27T09:44:58+00:00" - }, - { - "name": "phpunit/php-code-coverage", - "version": "9.2.32", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "85402a822d1ecf1db1096959413d35e1c37cf1a5" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/85402a822d1ecf1db1096959413d35e1c37cf1a5", - "reference": "85402a822d1ecf1db1096959413d35e1c37cf1a5", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-libxml": "*", - "ext-xmlwriter": "*", - "nikic/php-parser": "^4.19.1 || ^5.1.0", - "php": ">=7.3", - "phpunit/php-file-iterator": "^3.0.6", - "phpunit/php-text-template": "^2.0.4", - "sebastian/code-unit-reverse-lookup": "^2.0.3", - "sebastian/complexity": "^2.0.3", - "sebastian/environment": "^5.1.5", - "sebastian/lines-of-code": "^1.0.4", - "sebastian/version": "^3.0.2", - "theseer/tokenizer": "^1.2.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.6" - }, - "suggest": { - "ext-pcov": "PHP extension that provides line coverage", - "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "9.2.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", - "homepage": "https://github.com/sebastianbergmann/php-code-coverage", - "keywords": [ - "coverage", - "testing", - "xunit" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", - "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.32" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2024-08-22T04:23:01+00:00" - }, - { - "name": "phpunit/php-file-iterator", - "version": "3.0.6", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", - "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "FilterIterator implementation that filters files based on a list of suffixes.", - "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", - "keywords": [ - "filesystem", - "iterator" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", - "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/3.0.6" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2021-12-02T12:48:52+00:00" - }, - { - "name": "phpunit/php-invoker", - "version": "3.1.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-invoker.git", - "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/5a10147d0aaf65b58940a0b72f71c9ac0423cc67", - "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "ext-pcntl": "*", - "phpunit/phpunit": "^9.3" - }, - "suggest": { - "ext-pcntl": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.1-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Invoke callables with a timeout", - "homepage": "https://github.com/sebastianbergmann/php-invoker/", - "keywords": [ - "process" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-invoker/issues", - "source": "https://github.com/sebastianbergmann/php-invoker/tree/3.1.1" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-09-28T05:58:55+00:00" - }, - { - "name": "phpunit/php-text-template", - "version": "2.0.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", - "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Simple template engine.", - "homepage": "https://github.com/sebastianbergmann/php-text-template/", - "keywords": [ - "template" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-text-template/issues", - "source": "https://github.com/sebastianbergmann/php-text-template/tree/2.0.4" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T05:33:50+00:00" - }, - { - "name": "phpunit/php-timer", - "version": "5.0.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", - "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Utility class for timing", - "homepage": "https://github.com/sebastianbergmann/php-timer/", - "keywords": [ - "timer" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-timer/issues", - "source": "https://github.com/sebastianbergmann/php-timer/tree/5.0.3" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T13:16:10+00:00" - }, - { - "name": "phpunit/phpunit", - "version": "9.6.23", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "43d2cb18d0675c38bd44982a5d1d88f6d53d8d95" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/43d2cb18d0675c38bd44982a5d1d88f6d53d8d95", - "reference": "43d2cb18d0675c38bd44982a5d1d88f6d53d8d95", - "shasum": "" - }, - "require": { - "doctrine/instantiator": "^1.5.0 || ^2", - "ext-dom": "*", - "ext-json": "*", - "ext-libxml": "*", - "ext-mbstring": "*", - "ext-xml": "*", - "ext-xmlwriter": "*", - "myclabs/deep-copy": "^1.13.1", - "phar-io/manifest": "^2.0.4", - "phar-io/version": "^3.2.1", - "php": ">=7.3", - "phpunit/php-code-coverage": "^9.2.32", - "phpunit/php-file-iterator": "^3.0.6", - "phpunit/php-invoker": "^3.1.1", - "phpunit/php-text-template": "^2.0.4", - "phpunit/php-timer": "^5.0.3", - "sebastian/cli-parser": "^1.0.2", - "sebastian/code-unit": "^1.0.8", - "sebastian/comparator": "^4.0.8", - "sebastian/diff": "^4.0.6", - "sebastian/environment": "^5.1.5", - "sebastian/exporter": "^4.0.6", - "sebastian/global-state": "^5.0.7", - "sebastian/object-enumerator": "^4.0.4", - "sebastian/resource-operations": "^3.0.4", - "sebastian/type": "^3.2.1", - "sebastian/version": "^3.0.2" - }, - "suggest": { - "ext-soap": "To be able to generate mocks based on WSDL files", - "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" - }, - "bin": [ - "phpunit" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "9.6-dev" - } - }, - "autoload": { - "files": [ - "src/Framework/Assert/Functions.php" - ], - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "The PHP Unit Testing framework.", - "homepage": "https://phpunit.de/", - "keywords": [ - "phpunit", - "testing", - "xunit" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/phpunit/issues", - "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.23" - }, - "funding": [ - { - "url": "https://phpunit.de/sponsors.html", - "type": "custom" - }, - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - }, - { - "url": "https://liberapay.com/sebastianbergmann", - "type": "liberapay" - }, - { - "url": "https://thanks.dev/u/gh/sebastianbergmann", - "type": "thanks_dev" - }, - { - "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit", - "type": "tidelift" - } - ], - "time": "2025-05-02T06:40:34+00:00" - }, - { - "name": "sebastian/cli-parser", - "version": "1.0.2", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/cli-parser.git", - "reference": "2b56bea83a09de3ac06bb18b92f068e60cc6f50b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/2b56bea83a09de3ac06bb18b92f068e60cc6f50b", - "reference": "2b56bea83a09de3ac06bb18b92f068e60cc6f50b", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library for parsing CLI options", - "homepage": "https://github.com/sebastianbergmann/cli-parser", - "support": { - "issues": "https://github.com/sebastianbergmann/cli-parser/issues", - "source": "https://github.com/sebastianbergmann/cli-parser/tree/1.0.2" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2024-03-02T06:27:43+00:00" - }, - { - "name": "sebastian/code-unit", - "version": "1.0.8", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/code-unit.git", - "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/1fc9f64c0927627ef78ba436c9b17d967e68e120", - "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Collection of value objects that represent the PHP code units", - "homepage": "https://github.com/sebastianbergmann/code-unit", - "support": { - "issues": "https://github.com/sebastianbergmann/code-unit/issues", - "source": "https://github.com/sebastianbergmann/code-unit/tree/1.0.8" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T13:08:54+00:00" - }, - { - "name": "sebastian/code-unit-reverse-lookup", - "version": "2.0.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", - "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", - "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Looks up which function or method a line of code belongs to", - "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", - "support": { - "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", - "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/2.0.3" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-09-28T05:30:19+00:00" - }, - { - "name": "sebastian/comparator", - "version": "4.0.8", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "fa0f136dd2334583309d32b62544682ee972b51a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/fa0f136dd2334583309d32b62544682ee972b51a", - "reference": "fa0f136dd2334583309d32b62544682ee972b51a", - "shasum": "" - }, - "require": { - "php": ">=7.3", - "sebastian/diff": "^4.0", - "sebastian/exporter": "^4.0" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Volker Dusch", - "email": "github@wallbash.com" - }, - { - "name": "Bernhard Schussek", - "email": "bschussek@2bepublished.at" - } - ], - "description": "Provides the functionality to compare PHP values for equality", - "homepage": "https://github.com/sebastianbergmann/comparator", - "keywords": [ - "comparator", - "compare", - "equality" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/comparator/issues", - "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.8" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2022-09-14T12:41:17+00:00" - }, - { - "name": "sebastian/complexity", - "version": "2.0.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/complexity.git", - "reference": "25f207c40d62b8b7aa32f5ab026c53561964053a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/25f207c40d62b8b7aa32f5ab026c53561964053a", - "reference": "25f207c40d62b8b7aa32f5ab026c53561964053a", - "shasum": "" - }, - "require": { - "nikic/php-parser": "^4.18 || ^5.0", - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library for calculating the complexity of PHP code units", - "homepage": "https://github.com/sebastianbergmann/complexity", - "support": { - "issues": "https://github.com/sebastianbergmann/complexity/issues", - "source": "https://github.com/sebastianbergmann/complexity/tree/2.0.3" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-12-22T06:19:30+00:00" - }, - { - "name": "sebastian/diff", - "version": "4.0.6", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "ba01945089c3a293b01ba9badc29ad55b106b0bc" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/ba01945089c3a293b01ba9badc29ad55b106b0bc", - "reference": "ba01945089c3a293b01ba9badc29ad55b106b0bc", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3", - "symfony/process": "^4.2 || ^5" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Kore Nordmann", - "email": "mail@kore-nordmann.de" - } - ], - "description": "Diff implementation", - "homepage": "https://github.com/sebastianbergmann/diff", - "keywords": [ - "diff", - "udiff", - "unidiff", - "unified diff" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/diff/issues", - "source": "https://github.com/sebastianbergmann/diff/tree/4.0.6" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2024-03-02T06:30:58+00:00" - }, - { - "name": "sebastian/environment", - "version": "5.1.5", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", - "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "suggest": { - "ext-posix": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.1-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Provides functionality to handle HHVM/PHP environments", - "homepage": "http://www.github.com/sebastianbergmann/environment", - "keywords": [ - "Xdebug", - "environment", - "hhvm" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/environment/issues", - "source": "https://github.com/sebastianbergmann/environment/tree/5.1.5" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-02-03T06:03:51+00:00" - }, - { - "name": "sebastian/exporter", - "version": "4.0.6", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "78c00df8f170e02473b682df15bfcdacc3d32d72" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/78c00df8f170e02473b682df15bfcdacc3d32d72", - "reference": "78c00df8f170e02473b682df15bfcdacc3d32d72", - "shasum": "" - }, - "require": { - "php": ">=7.3", - "sebastian/recursion-context": "^4.0" - }, - "require-dev": { - "ext-mbstring": "*", - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Volker Dusch", - "email": "github@wallbash.com" - }, - { - "name": "Adam Harvey", - "email": "aharvey@php.net" - }, - { - "name": "Bernhard Schussek", - "email": "bschussek@gmail.com" - } - ], - "description": "Provides the functionality to export PHP variables for visualization", - "homepage": "https://www.github.com/sebastianbergmann/exporter", - "keywords": [ - "export", - "exporter" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/exporter/issues", - "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.6" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2024-03-02T06:33:00+00:00" - }, - { - "name": "sebastian/global-state", - "version": "5.0.7", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9", - "reference": "bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9", - "shasum": "" - }, - "require": { - "php": ">=7.3", - "sebastian/object-reflector": "^2.0", - "sebastian/recursion-context": "^4.0" - }, - "require-dev": { - "ext-dom": "*", - "phpunit/phpunit": "^9.3" - }, - "suggest": { - "ext-uopz": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Snapshotting of global state", - "homepage": "http://www.github.com/sebastianbergmann/global-state", - "keywords": [ - "global state" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/global-state/issues", - "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.7" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2024-03-02T06:35:11+00:00" - }, - { - "name": "sebastian/lines-of-code", - "version": "1.0.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/lines-of-code.git", - "reference": "e1e4a170560925c26d424b6a03aed157e7dcc5c5" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/e1e4a170560925c26d424b6a03aed157e7dcc5c5", - "reference": "e1e4a170560925c26d424b6a03aed157e7dcc5c5", - "shasum": "" - }, - "require": { - "nikic/php-parser": "^4.18 || ^5.0", - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library for counting the lines of code in PHP source code", - "homepage": "https://github.com/sebastianbergmann/lines-of-code", - "support": { - "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", - "source": "https://github.com/sebastianbergmann/lines-of-code/tree/1.0.4" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-12-22T06:20:34+00:00" - }, - { - "name": "sebastian/object-enumerator", - "version": "4.0.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/object-enumerator.git", - "reference": "5c9eeac41b290a3712d88851518825ad78f45c71" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/5c9eeac41b290a3712d88851518825ad78f45c71", - "reference": "5c9eeac41b290a3712d88851518825ad78f45c71", - "shasum": "" - }, - "require": { - "php": ">=7.3", - "sebastian/object-reflector": "^2.0", - "sebastian/recursion-context": "^4.0" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Traverses array structures and object graphs to enumerate all referenced objects", - "homepage": "https://github.com/sebastianbergmann/object-enumerator/", - "support": { - "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", - "source": "https://github.com/sebastianbergmann/object-enumerator/tree/4.0.4" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T13:12:34+00:00" - }, - { - "name": "sebastian/object-reflector", - "version": "2.0.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/object-reflector.git", - "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", - "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Allows reflection of object attributes, including inherited and non-public ones", - "homepage": "https://github.com/sebastianbergmann/object-reflector/", - "support": { - "issues": "https://github.com/sebastianbergmann/object-reflector/issues", - "source": "https://github.com/sebastianbergmann/object-reflector/tree/2.0.4" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T13:14:26+00:00" - }, - { - "name": "sebastian/recursion-context", - "version": "4.0.5", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", - "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Adam Harvey", - "email": "aharvey@php.net" - } - ], - "description": "Provides functionality to recursively process PHP variables", - "homepage": "https://github.com/sebastianbergmann/recursion-context", - "support": { - "issues": "https://github.com/sebastianbergmann/recursion-context/issues", - "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.5" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-02-03T06:07:39+00:00" - }, - { - "name": "sebastian/resource-operations", - "version": "3.0.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/resource-operations.git", - "reference": "05d5692a7993ecccd56a03e40cd7e5b09b1d404e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/05d5692a7993ecccd56a03e40cd7e5b09b1d404e", - "reference": "05d5692a7993ecccd56a03e40cd7e5b09b1d404e", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Provides a list of PHP built-in functions that operate on resources", - "homepage": "https://www.github.com/sebastianbergmann/resource-operations", - "support": { - "source": "https://github.com/sebastianbergmann/resource-operations/tree/3.0.4" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2024-03-14T16:00:52+00:00" - }, - { - "name": "sebastian/type", - "version": "3.2.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/type.git", - "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", - "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.5" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.2-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Collection of value objects that represent the types of the PHP type system", - "homepage": "https://github.com/sebastianbergmann/type", - "support": { - "issues": "https://github.com/sebastianbergmann/type/issues", - "source": "https://github.com/sebastianbergmann/type/tree/3.2.1" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-02-03T06:13:03+00:00" - }, - { - "name": "sebastian/version", - "version": "3.0.2", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/version.git", - "reference": "c6c1022351a901512170118436c764e473f6de8c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c6c1022351a901512170118436c764e473f6de8c", - "reference": "c6c1022351a901512170118436c764e473f6de8c", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library that helps with managing the version number of Git-hosted PHP projects", - "homepage": "https://github.com/sebastianbergmann/version", - "support": { - "issues": "https://github.com/sebastianbergmann/version/issues", - "source": "https://github.com/sebastianbergmann/version/tree/3.0.2" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-09-28T06:39:44+00:00" - }, - { - "name": "squizlabs/php_codesniffer", - "version": "3.13.0", - "source": { - "type": "git", - "url": "https://github.com/PHPCSStandards/PHP_CodeSniffer.git", - "reference": "65ff2489553b83b4597e89c3b8b721487011d186" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/65ff2489553b83b4597e89c3b8b721487011d186", - "reference": "65ff2489553b83b4597e89c3b8b721487011d186", - "shasum": "" - }, - "require": { - "ext-simplexml": "*", - "ext-tokenizer": "*", - "ext-xmlwriter": "*", - "php": ">=5.4.0" - }, - "require-dev": { - "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0 || ^8.0 || ^9.3.4" - }, - "bin": [ - "bin/phpcbf", - "bin/phpcs" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.x-dev" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Greg Sherwood", - "role": "Former lead" - }, - { - "name": "Juliette Reinders Folmer", - "role": "Current lead" - }, - { - "name": "Contributors", - "homepage": "https://github.com/PHPCSStandards/PHP_CodeSniffer/graphs/contributors" - } - ], - "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", - "homepage": "https://github.com/PHPCSStandards/PHP_CodeSniffer", - "keywords": [ - "phpcs", - "standards", - "static analysis" - ], - "support": { - "issues": "https://github.com/PHPCSStandards/PHP_CodeSniffer/issues", - "security": "https://github.com/PHPCSStandards/PHP_CodeSniffer/security/policy", - "source": "https://github.com/PHPCSStandards/PHP_CodeSniffer", - "wiki": "https://github.com/PHPCSStandards/PHP_CodeSniffer/wiki" - }, - "funding": [ - { - "url": "https://github.com/PHPCSStandards", - "type": "github" - }, - { - "url": "https://github.com/jrfnl", - "type": "github" - }, - { - "url": "https://opencollective.com/php_codesniffer", - "type": "open_collective" - }, - { - "url": "https://thanks.dev/u/gh/phpcsstandards", - "type": "thanks_dev" - } - ], - "time": "2025-05-11T03:36:00+00:00" - }, - { - "name": "theseer/tokenizer", - "version": "1.2.3", - "source": { - "type": "git", - "url": "https://github.com/theseer/tokenizer.git", - "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/theseer/tokenizer/zipball/737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", - "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-tokenizer": "*", - "ext-xmlwriter": "*", - "php": "^7.2 || ^8.0" - }, - "type": "library", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" - } - ], - "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", - "support": { - "issues": "https://github.com/theseer/tokenizer/issues", - "source": "https://github.com/theseer/tokenizer/tree/1.2.3" - }, - "funding": [ - { - "url": "https://github.com/theseer", - "type": "github" - } - ], - "time": "2024-03-03T12:36:25+00:00" - } - ], - "aliases": [], - "minimum-stability": "stable", - "stability-flags": {}, - "prefer-stable": false, - "prefer-lowest": false, - "platform": { - "php": ">=8.1" - }, - "platform-dev": {}, - "plugin-api-version": "2.6.0" -} diff --git a/demo/bad_job.php b/demo/bad_job.php new file mode 100644 index 0000000..cd719cc --- /dev/null +++ b/demo/bad_job.php @@ -0,0 +1,8 @@ +isTracking()) { 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) { fwrite(STDOUT, "Status of " . $argv[1] . " is: " . $status->get() . "\n"); sleep(1); -} +} \ No newline at end of file diff --git a/examples/Init.php b/demo/init.php similarity index 95% rename from examples/Init.php rename to demo/init.php index 11d4833..bdad7e5 100644 --- a/examples/Init.php +++ b/demo/init.php @@ -1,7 +1,4 @@ /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 \ No newline at end of file diff --git a/examples/SampleResquePlugin.php b/extras/sample-plugin.php similarity index 59% rename from examples/SampleResquePlugin.php rename to extras/sample-plugin.php index 1c2b2b3..ed5cf93 100644 --- a/examples/SampleResquePlugin.php +++ b/extras/sample-plugin.php @@ -1,17 +1,14 @@ + * @author Chris Boulton * @license http://www.opensource.org/licenses/mit-license.php */ class Resque { - public const VERSION = '2.5.3'; + const VERSION = '1.4'; - public const DEFAULT_INTERVAL = 5; + const DEFAULT_INTERVAL = 5; /** * @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 \Resque\Redis Instance of Resque_Redis. - * - * @throws \Resque\RedisException + * @return Resque_Redis Instance of Resque_Redis. + * @throws Resque_RedisException */ public static function redis() { - if (!is_null(self::$redis)) { + if (self::$redis !== null) { return self::$redis; } if (is_callable(self::$redisServer)) { self::$redis = call_user_func(self::$redisServer, self::$redisDatabase); } else { - self::$redis = new \Resque\Redis(self::$redisServer, self::$redisDatabase); + self::$redis = new Resque_Redis(self::$redisServer, self::$redisDatabase); } return self::$redis; @@ -92,7 +89,7 @@ class Resque $pid = pcntl_fork(); if ($pid === -1) { - throw new \RuntimeException('Unable to fork child worker.'); + throw new RuntimeException('Unable to fork child worker.'); } return $pid; @@ -104,23 +101,19 @@ class Resque * * @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. - * * @return bool */ - public static function push($queue, $item): bool + public static function push($queue, $item) { $encodedItem = json_encode($item); if ($encodedItem === false) { return false; } - self::redis()->sadd('queues', $queue); - $length = self::redis()->rpush('queue:' . $queue, $encodedItem); if ($length < 1) { return false; } - return true; } @@ -129,7 +122,6 @@ class Resque * return it. * * @param string $queue The name of the queue to fetch an item from. - * * @return mixed Decoded item from the queue. */ public static function pop($queue) @@ -150,7 +142,7 @@ class Resque * @param array $items * @return integer number of deleted items */ - public static function dequeue($queue, $items = []) + public static function dequeue($queue, $items = Array()) { if (count($items) > 0) { return self::removeItems($queue, $items); @@ -163,14 +155,13 @@ class Resque * Remove specified queue * * @param string $queue The name of the queue to remove. - * - * @return int Number of deleted items + * @return integer Number of deleted items */ - public static function removeQueue($queue): int + public static function removeQueue($queue) { $num = self::removeList($queue); self::redis()->srem('queues', $queue); - return intval($num); + return $num; } /** @@ -179,13 +170,12 @@ class Resque * * @param array $queues * @param int $timeout - * * @return array|null|void */ public static function blpop(array $queues, $timeout) { - $list = []; - foreach ($queues as $queue) { + $list = array(); + foreach ($queues AS $queue) { $list[] = 'queue:' . $queue; } @@ -202,10 +192,10 @@ class Resque */ $queue = substr($item[0], strlen(self::redis()->getPrefix() . 'queue:')); - return [ + return array( 'queue' => $queue, 'payload' => json_decode($item[1], true) - ]; + ); } /** @@ -215,9 +205,9 @@ class Resque * * @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) { $id = Resque::generateJobId(); - $hookParams = [ + $hookParams = array( 'class' => $class, 'args' => $args, 'queue' => $queue, 'id' => $id, - ]; + ); try { - \Resque\Event::trigger('beforeEnqueue', $hookParams); - } catch (\Resque\Job\DontCreate $e) { + Resque_Event::trigger('beforeEnqueue', $hookParams); + } catch (Resque_Job_DontCreate $e) { return false; } - \Resque\Job\Job::create($queue, $class, $args, $trackStatus, $id); - \Resque\Event::trigger('afterEnqueue', $hookParams); + Resque_Job::create($queue, $class, $args, $trackStatus, $id); + Resque_Event::trigger('afterEnqueue', $hookParams); return $id; } @@ -255,12 +245,11 @@ class Resque * Reserve and return the next available job in the specified queue. * * @param string $queue Queue to fetch next available job from. - * - * @return \Resque\Job\Job|null + * @return false|object|Resque_Job */ - 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. */ - public static function queues(): array + public static function 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 array $items - * - * @return int number of deleted items + * @return integer number of deleted items */ - private static function removeItems($queue, $items = []): int + private static function removeItems($queue, $items = Array()) { $counter = 0; $originalQueue = 'queue:' . $queue; @@ -352,11 +343,8 @@ class Resque # class name with args , example: item[0] = ['class' => {'foo' => 1, 'bar' => 2}] } elseif (is_array($val)) { $decodedArgs = (array)$decoded['args'][0]; - if ( - $decoded['class'] == $key - && count($decodedArgs) > 0 - && count(array_diff($decodedArgs, $val)) == 0 - ) { + if ($decoded['class'] == $key && + count($decodedArgs) > 0 && count(array_diff($decodedArgs, $val)) == 0) { return true; } # class name with ID, example: item[0] = ['class' => 'id'] @@ -377,7 +365,7 @@ class Resque * @params string $queue the name of the queue * @param $queue * @return integer number of deleted items belongs to this list - * @throws \Resque\RedisException + * @throws Resque_RedisException */ private static function removeList($queue) { diff --git a/src/Resque/Event.php b/lib/Resque/Event.php similarity index 88% rename from src/Resque/Event.php rename to lib/Resque/Event.php index f445375..2c8f182 100644 --- a/src/Resque/Event.php +++ b/lib/Resque/Event.php @@ -1,16 +1,14 @@ + * @author Chris Boulton * @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. @@ -22,7 +20,6 @@ class Event * * @param string $event Name of event to be raised. * @param mixed $data Optional, any data that should be passed to each callback. - * * @return true */ public static function trigger($event, $data = null) @@ -39,8 +36,7 @@ class Event if (!is_callable($callback)) { continue; } - - call_user_func_array($callback, array_values($data)); + call_user_func_array($callback, $data); } return true; @@ -50,8 +46,7 @@ class Event * Listen in on a given event to have a specified callback fired. * * @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 */ public static function listen($event, $callback) @@ -69,7 +64,6 @@ class Event * * @param string $event Name of event. * @param mixed $callback The callback as defined when listen() was called. - * * @return true */ public static function stopListening($event, $callback) @@ -88,10 +82,8 @@ class Event /** * Call all registered listeners. - * - * @return void */ - public static function clearListeners(): void + public static function clearListeners() { self::$events = []; } diff --git a/src/Resque/Exception.php b/lib/Resque/Exception.php similarity index 58% rename from src/Resque/Exception.php rename to lib/Resque/Exception.php index 7e8b7ae..fe510ca 100644 --- a/src/Resque/Exception.php +++ b/lib/Resque/Exception.php @@ -1,15 +1,13 @@ + * @author Chris Boulton * @license http://www.opensource.org/licenses/mit-license.php */ -class Exception extends \Exception +class Resque_Exception extends Exception { } diff --git a/src/Resque/Failure/Failure.php b/lib/Resque/Failure.php similarity index 71% rename from src/Resque/Failure/Failure.php rename to lib/Resque/Failure.php index 1a0b17f..d73fb6d 100644 --- a/src/Resque/Failure/Failure.php +++ b/lib/Resque/Failure.php @@ -1,16 +1,14 @@ + * @author Chris Boulton * @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. @@ -22,15 +20,11 @@ class Failure * * @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 \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. */ - public static function create( - $payload, - \Exception $exception, - \Resque\Worker $worker, - $queue - ) { + public static function create($payload, Exception $exception, Resque_Worker $worker, $queue) + { $backend = self::getBackend(); new $backend($payload, $exception, $worker, $queue); } @@ -38,12 +32,12 @@ class Failure /** * Return an instance of the backend for saving job failures. * - * @return string + * @return object|string */ public static function getBackend() { - if (is_null(self::$backend)) { - self::$backend = '\\Resque\\Failure\\ResqueFailureRedis'; + if (self::$backend === null) { + self::$backend = 'Resque_Failure_Redis'; } return self::$backend; @@ -55,11 +49,9 @@ class Failure * 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. - * - * @return void */ - public static function setBackend(string $backend): void + public static function setBackend($backend) { self::$backend = $backend; } -} +} \ No newline at end of file diff --git a/src/Resque/Failure/ResqueFailureInterface.php b/lib/Resque/Failure/Interface.php similarity index 81% rename from src/Resque/Failure/ResqueFailureInterface.php rename to lib/Resque/Failure/Interface.php index 980e656..d6da0e2 100644 --- a/src/Resque/Failure/ResqueFailureInterface.php +++ b/lib/Resque/Failure/Interface.php @@ -1,15 +1,13 @@ + * @package Resque/Failure + * @author Chris Boulton * @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). diff --git a/src/Resque/Failure/ResqueFailureRedis.php b/lib/Resque/Failure/Redis.php similarity index 73% rename from src/Resque/Failure/ResqueFailureRedis.php rename to lib/Resque/Failure/Redis.php index 33a9cc1..caff0d5 100644 --- a/src/Resque/Failure/ResqueFailureRedis.php +++ b/lib/Resque/Failure/Redis.php @@ -1,16 +1,13 @@ + * @package Resque/Failure + * @author Chris Boulton * @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). @@ -19,12 +16,11 @@ class ResqueFailureRedis implements ResqueFailureInterface * @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 string $queue The name of the queue the job was fetched from. - * @throws \Resque\RedisException */ public function __construct($payload, $exception, $worker, $queue) { - $data = new \stdClass(); - $data->failed_at = date('D M d H:i:s T Y'); + $data = new stdClass; + $data->failed_at = strftime('%a %b %d %H:%M:%S %Z %Y'); $data->payload = $payload; $data->exception = get_class($exception); $data->error = $exception->getMessage(); @@ -32,6 +28,6 @@ class ResqueFailureRedis implements ResqueFailureInterface $data->worker = (string)$worker; $data->queue = $queue; $data = json_encode($data); - \Resque\Resque::redis()->rpush('failed', $data); + Resque::redis()->rpush('failed', $data); } } diff --git a/src/Resque/Job/Job.php b/lib/Resque/Job.php similarity index 67% rename from src/Resque/Job/Job.php rename to lib/Resque/Job.php index 8249559..3a91cbc 100755 --- a/src/Resque/Job/Job.php +++ b/lib/Resque/Job.php @@ -1,16 +1,14 @@ + * @author Chris Boulton * @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. @@ -18,7 +16,7 @@ class Job 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; @@ -28,12 +26,12 @@ class Job 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; /** - * @var \Resque\Job\FactoryInterface + * @var Resque_Job_FactoryInterface */ private $jobFactory; @@ -59,21 +57,20 @@ class Job * @param string $id Unique identifier for tracking the job. Generated if not supplied. * * @return string - * * @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)) { - $id = \Resque\Resque::generateJobId(); + $id = Resque::generateJobId(); } if ($args !== null && !is_array($args)) { - throw new \InvalidArgumentException( + throw new InvalidArgumentException( 'Supplied $args must be an array.' ); } - \Resque\Resque::push($queue, [ + Resque::push($queue, [ 'class' => $class, 'args' => [$args], 'id' => $id, @@ -81,7 +78,7 @@ class Job ]); if ($monitor) { - Status::create($id); + Resque_Job_Status::create($id); } return $id; @@ -89,67 +86,62 @@ class Job /** * 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. - * - * @return Job|null Null when there aren't any waiting jobs, instance of \Resque\Job\Job when a job was found. + * @return false|object Null when there aren't any waiting jobs, instance of Resque_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)) { - 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 - * and return an instance of \Resque\Job\Job for it. + * and return an instance of Resque_Job for it. * * @param array $queues * @param int $timeout - * - * @return Job|null Null when there aren't any waiting jobs, instance of \Resque\Job\Job when a job was found. + * @return false|object Null when there aren't any waiting jobs, instance of Resque_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)) { - 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. * - * @param int $status Status constant from \Resque\Job\Status indicating the current status of a job. - * - * @return bool + * @param int $status Status constant from Resque_Job_Status indicating the current status of a job. */ - public function updateStatus($status): bool + public function updateStatus($status) { if (empty($this->payload['id'])) { - return false; + return; } - $statusInstance = new Status($this->payload['id']); + $statusInstance = new Resque_Job_Status($this->payload['id']); $statusInstance->update($status); - return true; } /** * 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() { - $status = new Status($this->payload['id']); + $status = new Resque_Job_Status($this->payload['id']); return $status->get(); } @@ -169,12 +161,11 @@ class Job /** * Get the instantiated object for this job that will be performing work. - * - * @return \Resque\Job\JobInterface Instance of the object that this job belongs to. + * @return Resque_JobInterface Instance of the object that this job belongs to. */ public function getInstance() { - if (isset($this->instance) && !is_null($this->instance)) { + if (!is_null($this->instance)) { return $this->instance; } @@ -188,13 +179,12 @@ class Job * associated with the job with the supplied arguments. * * @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() { try { - \Resque\Event::trigger('beforePerform', $this); + Resque_Event::trigger('beforePerform', $this); $instance = $this->getInstance(); if (method_exists($instance, 'setUp')) { @@ -207,9 +197,9 @@ class Job $instance->tearDown(); } - \Resque\Event::trigger('afterPerform', $this); - } catch (DontPerform $e) { - /** @noinspection PhpRedundantCatchClauseInspection */ + Resque_Event::trigger('afterPerform', $this); + } // beforePerform/setUp have said don't perform this job. Return. + /** @noinspection PhpRedundantCatchClauseInspection */ catch (Resque_Job_DontPerform $e) { return false; } @@ -223,30 +213,29 @@ class Job */ public function fail($exception) { - \Resque\Event::trigger('onFailure', [ + Resque_Event::trigger('onFailure', [ 'exception' => $exception, 'job' => $this, ]); - $this->updateStatus(Status::STATUS_FAILED); - \Resque\Failure\Failure::create( + $this->updateStatus(Resque_Job_Status::STATUS_FAILED); + Resque_Failure::create( $this->payload, $exception, $this->worker, $this->queue ); - \Resque\Stat::incr('failed'); - \Resque\Stat::incr('failed:' . $this->worker); + Resque_Stat::incr('failed'); + Resque_Stat::incr('failed:' . $this->worker); } /** * Re-queue the current job. - * * @return string */ public function recreate() { - $status = new Status($this->payload['id']); + $status = new Resque_Job_Status($this->payload['id']); $monitor = false; if ($status->isTracking()) { $monitor = true; @@ -276,11 +265,10 @@ class Job } /** - * @param FactoryInterface $jobFactory - * - * @return Job + * @param Resque_Job_FactoryInterface $jobFactory + * @return Resque_Job */ - public function setJobFactory(FactoryInterface $jobFactory) + public function setJobFactory(Resque_Job_FactoryInterface $jobFactory) { $this->jobFactory = $jobFactory; @@ -288,14 +276,13 @@ class Job } /** - * @return FactoryInterface + * @return Resque_Job_FactoryInterface */ public function getJobFactory() { - if (is_null($this->jobFactory)) { - $this->jobFactory = new Factory(); + if ($this->jobFactory === null) { + $this->jobFactory = new Resque_Job_Factory(); } - return $this->jobFactory; } } diff --git a/src/Resque/Job/DirtyExitException.php b/lib/Resque/Job/DirtyExitException.php similarity index 61% rename from src/Resque/Job/DirtyExitException.php rename to lib/Resque/Job/DirtyExitException.php index ba002bc..7b1f88b 100644 --- a/src/Resque/Job/DirtyExitException.php +++ b/lib/Resque/Job/DirtyExitException.php @@ -1,14 +1,13 @@ + * @author Chris Boulton * @license http://www.opensource.org/licenses/mit-license.php */ -class DirtyExitException extends \RuntimeException +class Resque_Job_DirtyExitException extends RuntimeException { + } diff --git a/src/Resque/Job/DontCreate.php b/lib/Resque/Job/DontCreate.php similarity index 65% rename from src/Resque/Job/DontCreate.php rename to lib/Resque/Job/DontCreate.php index 21f4f4d..931ae91 100644 --- a/src/Resque/Job/DontCreate.php +++ b/lib/Resque/Job/DontCreate.php @@ -1,14 +1,13 @@ + * @author Chris Boulton * @license http://www.opensource.org/licenses/mit-license.php */ -class DontCreate extends \Exception +class Resque_Job_DontCreate extends Exception { + } diff --git a/src/Resque/Job/DontPerform.php b/lib/Resque/Job/DontPerform.php similarity index 63% rename from src/Resque/Job/DontPerform.php rename to lib/Resque/Job/DontPerform.php index cc1c029..69075f4 100644 --- a/src/Resque/Job/DontPerform.php +++ b/lib/Resque/Job/DontPerform.php @@ -1,14 +1,14 @@ + * @author Chris Boulton * @license http://www.opensource.org/licenses/mit-license.php */ -class DontPerform extends \Exception + +class Resque_Job_DontPerform extends Exception { + } diff --git a/lib/Resque/Job/Factory.php b/lib/Resque/Job/Factory.php new file mode 100644 index 0000000..cf17294 --- /dev/null +++ b/lib/Resque/Job/Factory.php @@ -0,0 +1,32 @@ +args = $args; + $instance->queue = $queue; + return $instance; + } +} diff --git a/lib/Resque/Job/FactoryInterface.php b/lib/Resque/Job/FactoryInterface.php new file mode 100644 index 0000000..a1203e1 --- /dev/null +++ b/lib/Resque/Job/FactoryInterface.php @@ -0,0 +1,12 @@ + + * @author Chris Boulton * @license http://www.opensource.org/licenses/mit-license.php */ -class Status +class Resque_Job_Status { - public const STATUS_WAITING = 1; - public const STATUS_RUNNING = 2; - public const STATUS_FAILED = 3; - public const STATUS_COMPLETE = 4; + const STATUS_WAITING = 1; + const STATUS_RUNNING = 2; + const STATUS_FAILED = 3; + const STATUS_COMPLETE = 4; /** * @var string The ID of the job this status class refers back to. @@ -59,11 +57,7 @@ class Status 'updated' => time(), 'started' => time(), ]; - \Resque\Resque::redis()->set( - 'job:' . $id . ':status', - json_encode($statusPacket), - ['ex' => \Resque\Redis::DEFAULT_REDIS_TTL], - ); + Resque::redis()->set('job:' . $id . ':status', json_encode($statusPacket)); } /** @@ -72,13 +66,13 @@ class Status * * @return boolean True if the status is being monitored, false if not. */ - public function isTracking(): bool + public function isTracking() { if ($this->isTracking === false) { return false; } - if (!\Resque\Resque::redis()->exists((string)$this)) { + if (!Resque::redis()->exists((string)$this)) { $this->isTracking = false; return false; } @@ -90,7 +84,7 @@ class 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) { @@ -102,19 +96,19 @@ class Status 'status' => $status, 'updated' => time(), ]; + Resque::redis()->set((string)$this, json_encode($statusPacket)); - \Resque\Resque::redis()->set( - (string)$this, - json_encode($statusPacket), - ['ex' => \Resque\Redis::DEFAULT_REDIS_TTL], - ); + // Expire the status for completed jobs after 24 hours + if (in_array($status, self::$completeStatuses)) { + Resque::redis()->expire((string)$this, 86400); + } } /** * Fetch the status for the job being monitored. * * @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() { @@ -122,7 +116,7 @@ class Status return false; } - $statusPacket = json_decode(\Resque\Resque::redis()->get((string)$this), true); + $statusPacket = json_decode(Resque::redis()->get((string)$this), true); if (!$statusPacket) { return false; } @@ -132,12 +126,10 @@ class Status /** * 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); } /** @@ -145,7 +137,7 @@ class Status * * @return string String representation of the current job status class. */ - public function __toString(): string + public function __toString() { return 'job:' . $this->id . ':status'; } diff --git a/src/Resque/Job/JobInterface.php b/lib/Resque/JobInterface.php similarity index 62% rename from src/Resque/Job/JobInterface.php rename to lib/Resque/JobInterface.php index ed8b53c..f31281d 100644 --- a/src/Resque/Job/JobInterface.php +++ b/lib/Resque/JobInterface.php @@ -1,8 +1,6 @@ + * @package Resque/Stat + * @author Chris Boulton * @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 function __construct($logLevel = 'warning') + public function __construct($logLevel = "warning") { $this->logLevel = strtolower($logLevel); } @@ -25,34 +23,19 @@ class Log extends \Psr\Log\AbstractLogger * @param mixed $level PSR-3 log level constant, or equivalent string * @param string $message Message to log, may contain a { placeholder } * @param array $context Variables to replace { placeholder } - * * @return null */ - public function log($level, $message, array $context = []): void + public function log($level, $message, array $context = []) { - $logLevels = [ - 'emergency', - 'alert', - 'critical', - 'error', - 'warning', - 'notice', - 'info', - 'debug', - ]; - - /** - * 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. - */ + $logLevels = ["emergency", "alert", "critical", "error", "warning", "notice", "info", "debug"]; if (array_search($level, $logLevels) <= array_search($this->logLevel, $logLevels)) { fwrite( STDOUT, - '[' . $level . '][' . date('Y-m-d H:i:s') . '] ' . - $this->interpolate($message, $context) . PHP_EOL + '[' . $level . '][' . strftime('%T %Y-%m-%d') . '] ' . $this->interpolate($message, $context) . PHP_EOL ); } return; + } /** diff --git a/src/Resque/Redis.php b/lib/Resque/Redis.php similarity index 83% rename from src/Resque/Redis.php rename to lib/Resque/Redis.php index 5537b55..169e010 100644 --- a/src/Resque/Redis.php +++ b/lib/Resque/Redis.php @@ -1,27 +1,23 @@ + * @author Chris Boulton * @license http://www.opensource.org/licenses/mit-license.php */ -class Redis +class Resque_Redis { /** * Redis Client - * - * @var \Credis_Client + * @var Credis_Client */ private $driver; /** * Redis namespace - * * @var string */ private static $defaultNamespace = 'resque:'; @@ -29,22 +25,17 @@ class Redis /** * A default host to connect to */ - public const DEFAULT_HOST = 'localhost'; + const DEFAULT_HOST = 'localhost'; /** * The default Redis port */ - public const DEFAULT_PORT = 6379; + const DEFAULT_PORT = 6379; /** * The default Redis Database number */ - public const DEFAULT_DATABASE = 0; - - /** - * Default Redis TTL (2 days) - */ - public const DEFAULT_REDIS_TTL = 172800; + const DEFAULT_DATABASE = 0; /** * @var array List of all commands in Redis that supply a key as their @@ -97,20 +88,27 @@ class Redis 'rename', 'rpoplpush' ]; + // sinterstore + // sunion + // sunionstore + // sdiff + // sdiffstore + // sinter + // smove + // mget + // msetnx + // mset + // renamenx /** * Set Redis namespace (prefix) default: resque - * * @param string $namespace - * - * @return void */ - public static function prefix(string $namespace): void + public static function prefix($namespace) { if (substr($namespace, -1) !== ':' && $namespace != '') { $namespace .= ':'; } - self::$defaultNamespace = $namespace; } @@ -118,9 +116,8 @@ class Redis * @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 * DSN-supplied value will be used instead and this parameter is ignored. - * @param object $client Optional \Credis_Client instance instantiated by you - * - * @throws \Resque\RedisException + * @param object $client Optional Credis_Client instance instantiated by you + * @throws Resque_RedisException */ public function __construct($server, $database = null, $client = null) { @@ -134,7 +131,7 @@ class Redis $timeout = isset($options['timeout']) ? intval($options['timeout']) : null; $persistent = isset($options['persistent']) ? $options['persistent'] : ''; $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); if ($password) { $this->driver->auth($password); @@ -148,8 +145,8 @@ class Redis if ($database !== null) { $this->driver->select($database); } - } catch (\Exception $e) { - throw new RedisException('Error communicating with Redis: ' . $e->getMessage(), 0, $e); + } catch (Exception $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. * * @param string $dsn A DSN string - * * @return array An array of DSN compotnents, with 'false' values for any unknown components. e.g. * [host, port, db, user, pass, options] */ - public static function parseDsn($dsn): array + public static function parseDsn($dsn) { if ($dsn == '') { // 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 array $args Array of supplied arguments to the method. - * * @return mixed Return value from Resident::call() based on the command. - * * @throws Resque_RedisException */ public function __call($name, $args) { if (in_array($name, $this->keyCommands)) { if (is_array($args[0])) { - foreach ($args[0] as $i => $v) { + foreach ($args[0] AS $i => $v) { $args[0][$i] = self::$defaultNamespace . $v; } } else { @@ -253,18 +247,23 @@ class Redis } try { return $this->driver->__call($name, $args); - } catch (\Exception $e) { - throw new RedisException('Error communicating with Redis: ' . $e->getMessage(), 0, $e); + } catch (CredisException $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() { return self::$defaultNamespace; } + + public static function removePrefix($string) + { + $prefix = self::getPrefix(); + + if (substr($string, 0, strlen($prefix)) == $prefix) { + $string = substr($string, strlen($prefix), strlen($string)); + } + return $string; + } } diff --git a/lib/Resque/RedisException.php b/lib/Resque/RedisException.php new file mode 100644 index 0000000..0c2294e --- /dev/null +++ b/lib/Resque/RedisException.php @@ -0,0 +1,14 @@ + + * @license http://www.opensource.org/licenses/mit-license.php + */ + +class Resque_RedisException extends Resque_Exception +{ + +} diff --git a/src/Resque/Stat.php b/lib/Resque/Stat.php similarity index 55% rename from src/Resque/Stat.php rename to lib/Resque/Stat.php index 6cfa6c1..9855638 100644 --- a/src/Resque/Stat.php +++ b/lib/Resque/Stat.php @@ -1,25 +1,22 @@ + * @package Resque/Stat + * @author Chris Boulton * @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. * * @param string $stat The name of the statistic to get the stats for. - * - * @return int Value of the statistic. + * @return mixed Value of the statistic. */ - public static function get(string $stat): int + public static function get($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 int $by The amount to increment the statistic by. - * - * @return bool True if successful, false if not. + * @return boolean True if successful, false if not. */ - public static function incr(string $stat, int $by = 1): bool + public static function incr($stat, $by = 1) { - // Make sure we set a TTL by default - $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; + return (bool)Resque::redis()->incrby('stat:' . $stat, $by); } /** @@ -54,10 +38,9 @@ class Stat * * @param string $stat The name of the statistic to decrement. * @param int $by The amount to decrement the statistic by. - * - * @return bool True if successful, false if not. + * @return boolean True if successful, false if not. */ - public static function decr(string $stat, int $by = 1): bool + public static function decr($stat, $by = 1) { return (bool)Resque::redis()->decrby('stat:' . $stat, $by); } @@ -66,11 +49,10 @@ class Stat * Delete a statistic with the given name. * * @param string $stat The name of the statistic to delete. - * - * @return bool True if successful, false if not. + * @return boolean True if successful, false if not. */ - public static function clear(string $stat): bool + public static function clear($stat) { return (bool)Resque::redis()->del('stat:' . $stat); } -} +} \ No newline at end of file diff --git a/src/Resque/Worker.php b/lib/Resque/Worker.php similarity index 62% rename from src/Resque/Worker.php rename to lib/Resque/Worker.php index fc08303..d7a7aa9 100644 --- a/src/Resque/Worker.php +++ b/lib/Resque/Worker.php @@ -1,20 +1,17 @@ + * @package Resque/Worker + * @author Chris Boulton * @license http://www.opensource.org/licenses/mit-license.php */ -class Worker +class Resque_Worker { /** * @var LoggerInterface Logging object that impliments the PSR-3 LoggerInterface @@ -47,7 +44,7 @@ class Worker 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; @@ -69,7 +66,7 @@ class Worker */ public function __construct($queues) { - $this->logger = new Log(); + $this->logger = new Resque_Log(); if (!is_array($queues)) { $queues = [$queues]; @@ -83,10 +80,9 @@ class Worker /** * Return all workers known to Resque as instantiated instances. - * * @return array */ - public static function all(): array + public static function all() { $workers = Resque::redis()->smembers('workers'); if (!is_array($workers)) { @@ -97,20 +93,17 @@ class Worker foreach ($workers as $workerId) { $instances[] = self::find($workerId); } - return $instances; } /** * Given a worker ID, check if it is registered/valid. * - * @param string $workerId ID of the worker - * - * @return boolean True if the worker exists, false if not - * + * @param string $workerId ID of the worker. + * @return boolean True if the worker exists, false if not. * @throws Resque_RedisException */ - public static function exists($workerId): bool + public static function exists($workerId) { return (bool)Resque::redis()->sismember('workers', $workerId); } @@ -118,24 +111,20 @@ class Worker /** * Given a worker ID, find it and return an instantiated worker class for it. * - * @param string $workerId The ID of the worker - * - * @return Resque_Worker|bool - * + * @param string $workerId The ID of the worker. + * @return bool|Resque_Worker * @throws Resque_RedisException */ public static function find($workerId) { - if (false === strpos($workerId, ":") || !self::exists($workerId)) { + if (!self::exists($workerId) || false === strpos($workerId, ":")) { return false; } - /** @noinspection PhpUnusedLocalVariableInspection */ list($hostname, $pid, $queues) = explode(':', $workerId, 3); $queues = explode(',', $queues); $worker = new self($queues); $worker->setId($workerId); - return $worker; } @@ -143,10 +132,8 @@ class Worker * Set the ID of this worker to a given ID string. * * @param string $workerId ID for the worker. - * - * @return void */ - public function setId($workerId): void + public function setId($workerId) { $this->id = $workerId; } @@ -159,12 +146,9 @@ class Worker * * @param int $interval How often to check for new jobs across the queues. * @param bool $blocking - * - * @return void - * * @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->startup(); @@ -178,14 +162,8 @@ class Worker $job = false; if (!$this->paused) { if ($blocking === true) { - $this->logger->log( - \Psr\Log\LogLevel::INFO, - 'Starting blocking with timeout of {interval}', - ['interval' => $interval], - ); - $this->updateProcLine( - 'Waiting for ' . implode(',', $this->queues) . ' with blocking timeout ' . $interval - ); + $this->logger->log(Psr\Log\LogLevel::INFO, 'Starting blocking with timeout of {interval}', ['interval' => $interval]); + $this->updateProcLine('Waiting for ' . implode(',', $this->queues) . ' with blocking timeout ' . $interval); } else { $this->updateProcLine('Waiting for ' . implode(',', $this->queues) . ' with interval ' . $interval); } @@ -201,12 +179,7 @@ class Worker if ($blocking === false) { // If no job was found, we sleep for $interval before continuing and checking again - $this->logger->log( - \Psr\Log\LogLevel::INFO, - 'Sleeping for {interval}', - ['interval' => $interval], - ); - + $this->logger->log(Psr\Log\LogLevel::INFO, 'Sleeping for {interval}', ['interval' => $interval]); if ($this->paused) { $this->updateProcLine('Paused'); } else { @@ -219,19 +192,17 @@ class Worker continue; } - $this->logger->log(\Psr\Log\LogLevel::NOTICE, 'Starting work on {job}', ['job' => $job]); - Event::trigger('beforeFork', $job); + $this->logger->log(Psr\Log\LogLevel::NOTICE, 'Starting work on {job}', ['job' => $job]); + Resque_Event::trigger('beforeFork', $job); $this->workingOn($job); $this->child = Resque::fork(); // Forked and we're the child. Run the job. if ($this->child === 0 || $this->child === false) { - $status = 'Processing ' . $job->queue - . ' (' . ($job->payload['class'] ?? '') . ') since ' - . date('Y-m-d H:i:s'); + $status = 'Processing ' . $job->queue . ' since ' . strftime('%F %T'); $this->updateProcLine($status); - $this->logger->log(\Psr\Log\LogLevel::INFO, $status); + $this->logger->log(Psr\Log\LogLevel::INFO, $status); /** @noinspection PhpParamsInspection */ $this->perform($job); if ($this->child === 0) { @@ -241,15 +212,15 @@ class Worker if ($this->child > 0) { // 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->logger->log(\Psr\Log\LogLevel::INFO, $status); + $this->logger->log(Psr\Log\LogLevel::INFO, $status); // Wait until the child process finishes before continuing pcntl_wait($status); $exitStatus = pcntl_wexitstatus($status); if ($exitStatus !== 0) { - $job->fail(new \Resque\Job\DirtyExitException( + $job->fail(new Resque_Job_DirtyExitException( '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 - * - * @return void + * @param Resque_Job $job The job to be processed. */ - public function perform(\Resque\Job\Job $job): void + public function perform(Resque_Job $job) { try { - Event::trigger('afterFork', $job); + Resque_Event::trigger('afterFork', $job); $job->perform(); - } catch (\Exception $e) { - $this->logger->log(\Psr\Log\LogLevel::CRITICAL, '{job} has failed {stack}', ['job' => $job, 'stack' => $e]); + } catch (Exception $e) { + $this->logger->log(Psr\Log\LogLevel::CRITICAL, '{job} has failed {stack}', ['job' => $job, 'stack' => $e]); $job->fail($e); return; } - $job->updateStatus(\Resque\Job\Status::STATUS_COMPLETE); - $this->logger->log(\Psr\Log\LogLevel::NOTICE, '{job} has finished', ['job' => $job]); + $job->updateStatus(Resque_Job_Status::STATUS_COMPLETE); + $this->logger->log(Psr\Log\LogLevel::NOTICE, '{job} has finished', ['job' => $job]); } /** - * @param bool $blocking - * @param int $timeout - * - * @return object|boolean - Instance of \Resque\Job\Job if a job is found, false if not + * @param bool $blocking + * @param int $timeout + * @return object|boolean Instance of Resque_Job if a job is found, false if not. */ public function reserve($blocking = false, $timeout = null) { @@ -298,17 +266,17 @@ class Worker } if ($blocking === true) { - $job = \Resque\Job\Job::reserveBlocking($queues, $timeout); - if (!is_null($job)) { - $this->logger->log(\Psr\Log\LogLevel::INFO, 'Found job on {queue}', ['queue' => $job->queue]); + $job = Resque_Job::reserveBlocking($queues, $timeout); + if ($job) { + $this->logger->log(Psr\Log\LogLevel::INFO, 'Found job on {queue}', ['queue' => $job->queue]); return $job; } } else { foreach ($queues as $queue) { - $this->logger->log(\Psr\Log\LogLevel::INFO, 'Checking {queue} for jobs', ['queue' => $queue]); - $job = \Resque\Job\Job::reserve($queue); - if (!is_null($job)) { - $this->logger->log(\Psr\Log\LogLevel::INFO, 'Found job on {queue}', ['queue' => $job->queue]); + $this->logger->log(Psr\Log\LogLevel::INFO, 'Checking {queue} for jobs', ['queue' => $queue]); + $job = Resque_Job::reserve($queue); + if ($job) { + $this->logger->log(Psr\Log\LogLevel::INFO, 'Found job on {queue}', ['queue' => $job->queue]); return $job; } } @@ -319,17 +287,16 @@ class Worker /** * 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 - * alphabetic order. (@param boolean $fetch If true, and the queue is set to *, will fetch - * all queue names from redis + * alphabetic order. (@see $fetch) * - * @param boolean $fetch - * - * @return array Array of associated queues + * @param boolean $fetch If true, and the queue is set to *, will fetch + * all queue names from redis. + * @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) { return $this->queues; @@ -337,20 +304,17 @@ class Worker $queues = Resque::queues(); sort($queues); - return $queues; } /** - * Perform necessary actions to start a worker - * - * @return void + * Perform necessary actions to start a worker. */ - private function startup(): void + private function startup() { $this->registerSigHandlers(); $this->pruneDeadWorkers(); - Event::trigger('beforeFirstFork', $this); + Resque_Event::trigger('beforeFirstFork', $this); $this->registerWorker(); } @@ -359,16 +323,14 @@ class Worker * the name of the currently running process to indicate the current state * of a worker. * - * @param string $status The updated process title - * - * @return void + * @param string $status The updated process title. */ - private function updateProcLine($status): void + private function updateProcLine($status) { $processTitle = 'resque-' . Resque::VERSION . ': ' . $status; if (function_exists('cli_set_process_title') && PHP_OS !== 'Darwin') { cli_set_process_title($processTitle); - } elseif (function_exists('setproctitle')) { + } else if (function_exists('setproctitle')) { setproctitle($processTitle); } } @@ -380,10 +342,8 @@ class Worker * INT: Shutdown immediately and stop processing jobs. * QUIT: Shutdown after the current job finishes processing. * USR1: Kill the forked child immediately and continue processing jobs. - * - * @return void */ - private function registerSigHandlers(): void + private function registerSigHandlers() { if (!function_exists('pcntl_signal')) { return; @@ -395,51 +355,43 @@ class Worker pcntl_signal(SIGUSR1, [$this, 'killChild']); pcntl_signal(SIGUSR2, [$this, 'pauseProcessing']); 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 - * - * @return void + * Signal handler callback for USR2, pauses processing of new jobs. */ - 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; } /** * Signal handler callback for CONT, resumes worker allowing it to pick * 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; } /** * Schedule a worker for shutdown. Will finish processing the current job * 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->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 * currently running. - * - * @return void */ - public function shutdownNow(): void + public function shutdownNow() { $this->shutdown(); $this->killChild(); @@ -448,27 +400,21 @@ class Worker /** * Kill a forked child job immediately. The job it is processing will not * be completed. - * - * @return void */ - public function killChild(): void + public function killChild() { 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; } - $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) { - $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); $this->child = null; } else { - $this->logger->log( - \Psr\Log\LogLevel::INFO, - 'Child {child} not found, restarting.', - ['child' => $this->child], - ); + $this->logger->log(Psr\Log\LogLevel::INFO, 'Child {child} not found, restarting.', ['child' => $this->child]); $this->shutdown(); } } @@ -480,10 +426,8 @@ class Worker * 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 * and therefore leave state information in Redis. - * - * @return void */ - public function pruneDeadWorkers(): void + public function pruneDeadWorkers() { $workerPids = $this->workerPids(); $workers = self::all(); @@ -493,11 +437,7 @@ class Worker if ($host != $this->hostname || in_array($pid, $workerPids) || $pid == getmypid()) { continue; } - $this->logger->log( - \Psr\Log\LogLevel::INFO, - 'Pruning dead worker: {worker}', - ['worker' => (string)$worker], - ); + $this->logger->log(Psr\Log\LogLevel::INFO, 'Pruning dead worker: {worker}', ['worker' => (string)$worker]); $worker->unregisterWorker(); } } @@ -509,7 +449,7 @@ class Worker * * @return array Array of Resque worker process IDs. */ - public function workerPids(): array + public function workerPids() { $pids = []; exec('ps -A -o pid,command | grep [r]esque', $cmdOutput); @@ -521,122 +461,104 @@ class Worker /** * Register this worker in Redis. - * 48 hour TTL so we don't pollute the redis db on server termination. - * - * @return void + * 48 hour TTL so we don't pollute the db on server termination. */ - public function registerWorker(): void + public function registerWorker() { Resque::redis()->sadd('workers', (string)$this); - Resque::redis()->set( - 'worker:' . (string)$this . ':started', - date('D M d H:i:s T Y'), - ['ex' => Redis::DEFAULT_REDIS_TTL], - ); + Resque::redis()->setex('worker:' . (string)$this . ':started', 172800, strftime('%a %b %d %H:%M:%S %Z %Y')); } /** * Unregister this worker in Redis. (shutdown etc) - * - * @return void */ - public function unregisterWorker(): void + public function unregisterWorker() { if (is_object($this->currentJob)) { - $this->currentJob->fail(new \Resque\Job\DirtyExitException()); + $this->currentJob->fail(new Resque_Job_DirtyExitException); } $id = (string)$this; Resque::redis()->srem('workers', $id); Resque::redis()->del('worker:' . $id); Resque::redis()->del('worker:' . $id . ':started'); - Stat::clear('processed:' . $id); - Stat::clear('failed:' . $id); + Resque_Stat::clear('processed:' . $id); + Resque_Stat::clear('failed:' . $id); } /** - * 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 + * Tell Redis which job we're currently working on. * + * @param Resque_Job $job Resque_Job instance containing the job we're working on. * @throws Resque_RedisException */ - public function workingOn(\Resque\Job\Job $job): void + public function workingOn(Resque_Job $job) { $job->worker = $this; $this->currentJob = $job; - $job->updateStatus(\Resque\Job\Status::STATUS_RUNNING); + $job->updateStatus(Resque_Job_Status::STATUS_RUNNING); $data = json_encode([ '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 ]); - - Resque::redis()->set( - 'worker:' . $job->worker, - $data, - ['ex' => Redis::DEFAULT_REDIS_TTL], - ); + Resque::redis()->set('worker:' . $job->worker, $data); } /** * Notify Redis that we've finished working on a job, clearing the working - * state and incrementing the job stats - * - * @return void + * state and incrementing the job stats. */ - public function doneWorking(): void + public function doneWorking() { $this->currentJob = null; - Stat::incr('processed'); - Stat::incr('processed:' . (string)$this); + Resque_Stat::incr('processed'); + Resque_Stat::incr('processed:' . (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() { $job = Resque::redis()->get('worker:' . $this); - - return $job ? json_decode($job, true) : []; + if (!$job) { + return []; + } else { + return json_decode($job, true); + } } /** - * Get a statistic belonging to this worker + * Get a statistic belonging to this worker. * * @param string $stat Statistic to fetch. - * * @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 * - * @param \Psr\Log\LoggerInterface $logger - * - * @return void + * @param Psr\Log\LoggerInterface $logger */ - public function setLogger(\Psr\Log\LoggerInterface $logger): void + public function setLogger(Psr\Log\LoggerInterface $logger) { $this->logger = $logger; } diff --git a/phpunit.xml b/phpunit.xml.dist similarity index 58% rename from phpunit.xml rename to phpunit.xml.dist index c718913..61d2d7b 100644 --- a/phpunit.xml +++ b/phpunit.xml.dist @@ -1,17 +1,24 @@ - ./tests/Resque/ + ./test/Resque/ + + + + ./lib/Resque/ + + \ No newline at end of file diff --git a/ruleset.xml b/ruleset.xml deleted file mode 100644 index 6bd9f60..0000000 --- a/ruleset.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - PHP8.2 Ruleset - - . - vendor - tests/ - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Resque/Job/Factory.php b/src/Resque/Job/Factory.php deleted file mode 100644 index 9ee0b74..0000000 --- a/src/Resque/Job/Factory.php +++ /dev/null @@ -1,50 +0,0 @@ - - * @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; - } -} diff --git a/src/Resque/Job/FactoryInterface.php b/src/Resque/Job/FactoryInterface.php deleted file mode 100644 index a44d6ac..0000000 --- a/src/Resque/Job/FactoryInterface.php +++ /dev/null @@ -1,22 +0,0 @@ - - * @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); -} diff --git a/src/Resque/RedisException.php b/src/Resque/RedisException.php deleted file mode 100644 index c875887..0000000 --- a/src/Resque/RedisException.php +++ /dev/null @@ -1,15 +0,0 @@ - - * @license http://www.opensource.org/licenses/mit-license.php - */ - -class RedisException extends \Exception -{ -} diff --git a/tests/Resque/Tests/EventTest.php b/test/Resque/Tests/EventTest.php similarity index 73% rename from tests/Resque/Tests/EventTest.php rename to test/Resque/Tests/EventTest.php index 9e9346f..24a83c7 100644 --- a/tests/Resque/Tests/EventTest.php +++ b/test/Resque/Tests/EventTest.php @@ -1,45 +1,43 @@ + * @author Chris Boulton * @license http://www.opensource.org/licenses/mit-license.php */ -class EventTest extends TestCase +class Resque_Tests_EventTest extends Resque_Tests_TestCase { private $callbacksHit = []; private $worker; - public function setUp(): void + public function setUp() { - TestJob::$called = false; + Test_Job::$called = false; // Register a worker to test with - $this->worker = new \Resque\Worker('jobs'); - $this->worker->setLogger(new \Resque\Log()); + $this->worker = new Resque_Worker('jobs'); + $this->worker->setLogger(new Resque_Log()); $this->worker->registerWorker(); } - public function tearDown(): void + public function tearDown() { - \Resque\Event::clearListeners(); + Resque_Event::clearListeners(); $this->callbacksHit = []; } public function getEventTestJob() { $payload = [ - 'class' => '\Resque\Test\TestJob', + 'class' => 'Test_Job', 'args' => [ ['somevar'], ], ]; - $job = new \Resque\Job\Job('jobs', $payload); + $job = new Resque_Job('jobs', $payload); $job->worker = $this->worker; return $job; } @@ -60,7 +58,7 @@ class EventTest extends TestCase */ public function testEventCallbacksFire($event, $callback) { - \Resque\Event::listen($event, [$this, $callback]); + Resque_Event::listen($event, [$this, $callback]); $job = $this->getEventTestJob(); $this->worker->perform($job); @@ -74,8 +72,8 @@ class EventTest extends TestCase $event = 'beforeFork'; $callback = 'beforeForkEventCallback'; - \Resque\Event::listen($event, [$this, $callback]); - \Resque\Resque::enqueue('jobs', '\Resque\Test\TestJob', [ + Resque_Event::listen($event, [$this, $callback]); + Resque::enqueue('jobs', 'Test_Job', [ 'somevar' ]); $this->getEventTestJob(); @@ -88,8 +86,8 @@ class EventTest extends TestCase $event = 'beforeEnqueue'; $callback = 'beforeEnqueueEventCallback'; - \Resque\Event::listen($event, [$this, $callback]); - \Resque\Resque::enqueue('jobs', '\Resque\Test\TestJob', [ + Resque_Event::listen($event, [$this, $callback]); + Resque::enqueue('jobs', 'Test_Job', [ 'somevar' ]); $this->assertContains($callback, $this->callbacksHit, $event . ' callback (' . $callback . ') was not called'); @@ -98,22 +96,22 @@ class EventTest extends TestCase public function testBeforePerformEventCanStopWork() { $callback = 'beforePerformEventDontPerformCallback'; - \Resque\Event::listen('beforePerform', [$this, $callback]); + Resque_Event::listen('beforePerform', [$this, $callback]); $job = $this->getEventTestJob(); $this->assertFalse($job->perform()); $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() { $callback = 'beforeEnqueueEventDontCreateCallback'; - \Resque\Event::listen('beforeEnqueue', [$this, $callback]); - \Resque\Event::listen('afterEnqueue', [$this, 'afterEnqueueEventCallback']); + Resque_Event::listen('beforeEnqueue', [$this, $callback]); + 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->assertNotContains('afterEnqueueEventCallback', $this->callbacksHit, 'afterEnqueue was still called, even though it should not have been'); $this->assertFalse($result); @@ -124,8 +122,8 @@ class EventTest extends TestCase $callback = 'afterEnqueueEventCallback'; $event = 'afterEnqueue'; - \Resque\Event::listen($event, [$this, $callback]); - \Resque\Resque::enqueue('jobs', '\Resque\Test\TestJob', [ + Resque_Event::listen($event, [$this, $callback]); + Resque::enqueue('jobs', 'Test_Job', [ 'somevar' ]); $this->assertContains($callback, $this->callbacksHit, $event . ' callback (' . $callback . ') was not called'); @@ -136,8 +134,8 @@ class EventTest extends TestCase $callback = 'beforePerformEventCallback'; $event = 'beforePerform'; - \Resque\Event::listen($event, [$this, $callback]); - \Resque\Event::stopListening($event, [$this, $callback]); + Resque_Event::listen($event, [$this, $callback]); + Resque_Event::stopListening($event, [$this, $callback]); $job = $this->getEventTestJob(); $this->worker->perform($job); @@ -151,20 +149,20 @@ class EventTest extends TestCase public function beforePerformEventDontPerformCallback() { $this->callbacksHit[] = __FUNCTION__; - throw new \Resque\Job\DontPerform(); + throw new Resque_Job_DontPerform(); } public function beforeEnqueueEventDontCreateCallback() { $this->callbacksHit[] = __FUNCTION__; - throw new \Resque\Job\DontCreate(); + throw new Resque_Job_DontCreate(); } public function assertValidEventCallback($function, $job) { $this->callbacksHit[] = $function; - if (!$job instanceof \Resque\Job\Job) { - $this->fail('Callback job argument is not an instance of \Resque\Job\Job'); + if (!$job instanceof Resque_Job) { + $this->fail('Callback job argument is not an instance of Resque_Job'); } $args = $job->getArguments(); $this->assertEquals($args[0], 'somevar'); @@ -173,7 +171,7 @@ class EventTest extends TestCase public function afterEnqueueEventCallback($class, $args) { $this->callbacksHit[] = __FUNCTION__; - $this->assertEquals('\Resque\Test\TestJob', $class); + $this->assertEquals('Test_Job', $class); $this->assertEquals([ 'somevar', ], $args); diff --git a/test/Resque/Tests/JobStatusTest.php b/test/Resque/Tests/JobStatusTest.php new file mode 100644 index 0000000..b2120ba --- /dev/null +++ b/test/Resque/Tests/JobStatusTest.php @@ -0,0 +1,109 @@ + + * @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()); + } +} \ No newline at end of file diff --git a/test/Resque/Tests/JobTest.php b/test/Resque/Tests/JobTest.php new file mode 100644 index 0000000..ada26cb --- /dev/null +++ b/test/Resque/Tests/JobTest.php @@ -0,0 +1,417 @@ + + * @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(); + } +} diff --git a/tests/Resque/Tests/LogTest.php b/test/Resque/Tests/LogTest.php similarity index 76% rename from tests/Resque/Tests/LogTest.php rename to test/Resque/Tests/LogTest.php index 18109b9..76a74d1 100644 --- a/tests/Resque/Tests/LogTest.php +++ b/test/Resque/Tests/LogTest.php @@ -1,20 +1,18 @@ + * @author Chris Boulton * @license http://www.opensource.org/licenses/mit-license.php */ -class LogTest extends TestCase +class Resque_Tests_LogTest extends Resque_Tests_TestCase { public function testLogInterpolate() { - $logger = new \Resque\Log(); + $logger = new Resque_Log(); $actual = $logger->interpolate('string {replace}', ['replace' => 'value']); $expected = 'string value'; @@ -23,7 +21,7 @@ class LogTest extends TestCase public function testLogInterpolateMutiple() { - $logger = new \Resque\Log(); + $logger = new Resque_Log(); $actual = $logger->interpolate( 'string {replace1} {replace2}', ['replace1' => 'value1', 'replace2' => 'value2'] diff --git a/tests/Resque/Tests/RedisTest.php b/test/Resque/Tests/RedisTest.php similarity index 87% rename from tests/Resque/Tests/RedisTest.php rename to test/Resque/Tests/RedisTest.php index b834f93..7e9a346 100644 --- a/tests/Resque/Tests/RedisTest.php +++ b/test/Resque/Tests/RedisTest.php @@ -1,25 +1,18 @@ + * @author Chris Boulton * @license http://www.opensource.org/licenses/mit-license.php */ -class RedisTest extends TestCase +class Resque_Tests_RedisTest extends Resque_Tests_TestCase { public function testRedisGetSet() { - $this->redis->set( - 'testKey', - 24, - ['ex' => \Resque\Redis::DEFAULT_REDIS_TTL], - ); - + $this->redis->set("testKey", 24); $val = $this->redis->get("testKey"); $this->assertEquals(24, $val); } @@ -35,14 +28,14 @@ class RedisTest extends TestCase // Input , Expected output ['', [ 'localhost', - \Resque\Redis::DEFAULT_PORT, + Resque_Redis::DEFAULT_PORT, false, false, false, [], ]], ['localhost', [ 'localhost', - \Resque\Redis::DEFAULT_PORT, + Resque_Redis::DEFAULT_PORT, false, false, false, [], @@ -63,14 +56,14 @@ class RedisTest extends TestCase ]], ['redis://foobar', [ 'foobar', - \Resque\Redis::DEFAULT_PORT, + Resque_Redis::DEFAULT_PORT, false, false, false, [], ]], ['redis://foobar/', [ 'foobar', - \Resque\Redis::DEFAULT_PORT, + Resque_Redis::DEFAULT_PORT, false, false, false, [], @@ -182,20 +175,18 @@ class RedisTest extends TestCase */ public function testParsingValidDsnString($dsn, $expected) { - $result = \Resque\Redis::parseDsn($dsn); + $result = Resque_Redis::parseDsn($dsn); $this->assertEquals($expected, $result); } /** * @dataProvider bogusDsnStringProvider - * - * @expectedException \InvalidArgumentException - * + * @expectedException InvalidArgumentException * @param $dsn */ public function testParsingBogusDsnStringThrowsException($dsn) { - $this->expectException(\InvalidArgumentException::class); - \Resque\Redis::parseDsn($dsn); + // The next line should throw an InvalidArgumentException + Resque_Redis::parseDsn($dsn); } } \ No newline at end of file diff --git a/tests/Resque/Tests/StatTest.php b/test/Resque/Tests/StatTest.php similarity index 54% rename from tests/Resque/Tests/StatTest.php rename to test/Resque/Tests/StatTest.php index 3b04c3d..121aaff 100644 --- a/tests/Resque/Tests/StatTest.php +++ b/test/Resque/Tests/StatTest.php @@ -1,53 +1,51 @@ + * @author Chris Boulton * @license http://www.opensource.org/licenses/mit-license.php */ -class StatTest extends TestCase +class Resque_Tests_StatTest extends Resque_Tests_TestCase { 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')); } public function testStatCanBeIncrementedByX() { - \Resque\Stat::incr('test_incrX', 10); - \Resque\Stat::incr('test_incrX', 11); + Resque_Stat::incr('test_incrX', 10); + Resque_Stat::incr('test_incrX', 11); $this->assertEquals(21, $this->redis->get('resque:stat:test_incrX')); } public function testStatCanBeDecremented() { - \Resque\Stat::incr('test_decr', 22); - \Resque\Stat::decr('test_decr'); + Resque_Stat::incr('test_decr', 22); + Resque_Stat::decr('test_decr'); $this->assertEquals(21, $this->redis->get('resque:stat:test_decr')); } public function testStatCanBeDecrementedByX() { - \Resque\Stat::incr('test_decrX', 22); - \Resque\Stat::decr('test_decrX', 11); + Resque_Stat::incr('test_decrX', 22); + Resque_Stat::decr('test_decrX', 11); $this->assertEquals(11, $this->redis->get('resque:stat:test_decrX')); } public function testGetStatByName() { - \Resque\Stat::incr('test_get', 100); - $this->assertEquals(100, \Resque\Stat::get('test_get')); + Resque_Stat::incr('test_get', 100); + $this->assertEquals(100, Resque_Stat::get('test_get')); } public function testGetUnknownStatReturns0() { - $this->assertEquals(0, \Resque\Stat::get('test_get_unknown')); + $this->assertEquals(0, Resque_Stat::get('test_get_unknown')); } } \ No newline at end of file diff --git a/tests/Resque/Tests/TestCase.php b/test/Resque/Tests/TestCase.php similarity index 51% rename from tests/Resque/Tests/TestCase.php rename to test/Resque/Tests/TestCase.php index d184010..aa348d5 100644 --- a/tests/Resque/Tests/TestCase.php +++ b/test/Resque/Tests/TestCase.php @@ -1,31 +1,28 @@ + * @author Chris Boulton * @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 $redis; - public static function setUpBeforeClass(): void + public static function setUpBeforeClass() { date_default_timezone_set('UTC'); } - public function setUp(): void + public function setUp() { // Setup redis connection for testing. - global $redisTestServer; - - $this->redis = new \Credis_Client($redisTestServer, '6379'); - \Resque\Resque::setBackend($redisTestServer); + $this->redis = new Credis_Client('localhost', '6379'); + Resque::setBackend('localhost'); $this->redis->flushAll(); } } diff --git a/tests/Resque/Tests/WorkerTest.php b/test/Resque/Tests/WorkerTest.php similarity index 55% rename from tests/Resque/Tests/WorkerTest.php rename to test/Resque/Tests/WorkerTest.php index e1b22e4..6dbd38b 100644 --- a/tests/Resque/Tests/WorkerTest.php +++ b/test/Resque/Tests/WorkerTest.php @@ -1,21 +1,19 @@ + * @author Chris Boulton * @license http://www.opensource.org/licenses/mit-license.php */ -class WorkerTest extends TestCase +class Resque_Tests_WorkerTest extends Resque_Tests_TestCase { public function testWorkerRegistersInList() { - $worker = new \Resque\Worker('*'); - $worker->setLogger(new \Resque\Log()); + $worker = new Resque_Worker('*'); + $worker->setLogger(new Resque_Log()); $worker->registerWorker(); // Make sure the worker is in the list @@ -27,76 +25,76 @@ class WorkerTest extends TestCase $num = 3; // Register a few workers for ($i = 0; $i < $num; ++$i) { - $worker = new \Resque\Worker('queue_' . $i); - $worker->setLogger(new \Resque\Log()); + $worker = new Resque_Worker('queue_' . $i); + $worker->setLogger(new Resque_Log()); $worker->registerWorker(); } // Now try to get them - $this->assertEquals($num, count(\Resque\Worker::all())); + $this->assertEquals($num, count(Resque_Worker::all())); } public function testGetWorkerById() { - $worker = new \Resque\Worker('*'); - $worker->setLogger(new \Resque\Log()); + $worker = new Resque_Worker('*'); + $worker->setLogger(new Resque_Log()); $worker->registerWorker(); - $newWorker = \Resque\Worker::find((string)$worker); + $newWorker = Resque_Worker::find((string)$worker); $this->assertEquals((string)$worker, (string)$newWorker); } public function testInvalidWorkerDoesNotExist() { - $this->assertFalse(\Resque\Worker::exists('blah')); + $this->assertFalse(Resque_Worker::exists('blah')); } public function testWorkerCanUnregister() { - $worker = new \Resque\Worker('*'); - $worker->setLogger(new \Resque\Log()); + $worker = new Resque_Worker('*'); + $worker->setLogger(new Resque_Log()); $worker->registerWorker(); $worker->unregisterWorker(); - $this->assertFalse(\Resque\Worker::exists((string)$worker)); - $this->assertEquals([], \Resque\Worker::all()); + $this->assertFalse(Resque_Worker::exists((string)$worker)); + $this->assertEquals([], Resque_Worker::all()); $this->assertEquals([], $this->redis->smembers('resque:workers')); } public function testPausedWorkerDoesNotPickUpJobs() { - $worker = new \Resque\Worker('*'); - $worker->setLogger(new \Resque\Log()); + $worker = new Resque_Worker('*'); + $worker->setLogger(new Resque_Log()); $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')); } public function testResumedWorkerPicksUpJobs() { - $worker = new \Resque\Worker('*'); - $worker->setLogger(new \Resque\Log()); + $worker = new Resque_Worker('*'); + $worker->setLogger(new Resque_Log()); $worker->pauseProcessing(); - \Resque\Resque::enqueue('jobs', '\Resque\Test\TestJob'); + Resque::enqueue('jobs', 'Test_Job'); $worker->work(0); - $this->assertEquals(0, \Resque\Stat::get('processed')); + $this->assertEquals(0, Resque_Stat::get('processed')); $worker->unPauseProcessing(); $worker->work(0); - $this->assertEquals(1, \Resque\Stat::get('processed')); + $this->assertEquals(1, Resque_Stat::get('processed')); } public function testWorkerCanWorkOverMultipleQueues() { - $worker = new \Resque\Worker([ + $worker = new Resque_Worker([ 'queue1', 'queue2' ]); - $worker->setLogger(new \Resque\Log()); + $worker->setLogger(new Resque_Log()); $worker->registerWorker(); - \Resque\Resque::enqueue('queue1', '\Resque\Test\TestJob_1'); - \Resque\Resque::enqueue('queue2', '\Resque\Test\TestJob_2'); + Resque::enqueue('queue1', 'Test_Job_1'); + Resque::enqueue('queue2', 'Test_Job_2'); $job = $worker->reserve(); $this->assertEquals('queue1', $job->queue); @@ -107,18 +105,18 @@ class WorkerTest extends TestCase public function testWorkerWorksQueuesInSpecifiedOrder() { - $worker = new \Resque\Worker([ + $worker = new Resque_Worker([ 'high', 'medium', 'low' ]); - $worker->setLogger(new \Resque\Log()); + $worker->setLogger(new Resque_Log()); $worker->registerWorker(); // Queue the jobs in a different order - \Resque\Resque::enqueue('low', '\Resque\Test\TestJob_1'); - \Resque\Resque::enqueue('high', '\Resque\Test\TestJob_2'); - \Resque\Resque::enqueue('medium', '\Resque\Test\TestJob_3'); + Resque::enqueue('low', 'Test_Job_1'); + Resque::enqueue('high', 'Test_Job_2'); + Resque::enqueue('medium', 'Test_Job_3'); // Now check we get the jobs back in the right order $job = $worker->reserve(); @@ -133,12 +131,12 @@ class WorkerTest extends TestCase public function testWildcardQueueWorkerWorksAllQueues() { - $worker = new \Resque\Worker('*'); - $worker->setLogger(new \Resque\Log()); + $worker = new Resque_Worker('*'); + $worker->setLogger(new Resque_Log()); $worker->registerWorker(); - \Resque\Resque::enqueue('queue1', '\Resque\Test\TestJob_1'); - \Resque\Resque::enqueue('queue2', '\Resque\Test\TestJob_2'); + Resque::enqueue('queue1', 'Test_Job_1'); + Resque::enqueue('queue2', 'Test_Job_2'); $job = $worker->reserve(); $this->assertEquals('queue1', $job->queue); @@ -149,19 +147,19 @@ class WorkerTest extends TestCase public function testWorkerDoesNotWorkOnUnknownQueues() { - $worker = new \Resque\Worker('queue1'); - $worker->setLogger(new \Resque\Log()); + $worker = new Resque_Worker('queue1'); + $worker->setLogger(new Resque_Log()); $worker->registerWorker(); - \Resque\Resque::enqueue('queue2', '\Resque\Test\TestJob'); + Resque::enqueue('queue2', 'Test_Job'); $this->assertFalse($worker->reserve()); } public function testWorkerClearsItsStatusWhenNotWorking() { - \Resque\Resque::enqueue('jobs', '\Resque\Test\TestJob'); - $worker = new \Resque\Worker('jobs'); - $worker->setLogger(new \Resque\Log()); + Resque::enqueue('jobs', 'Test_Job'); + $worker = new Resque_Worker('jobs'); + $worker->setLogger(new Resque_Log()); $job = $worker->reserve(); $worker->workingOn($job); $worker->doneWorking(); @@ -170,14 +168,14 @@ class WorkerTest extends TestCase public function testWorkerRecordsWhatItIsWorkingOn() { - $worker = new \Resque\Worker('jobs'); - $worker->setLogger(new \Resque\Log()); + $worker = new Resque_Worker('jobs'); + $worker->setLogger(new Resque_Log()); $worker->registerWorker(); $payload = [ - 'class' => '\Resque\Test\TestJob' + 'class' => 'Test_Job' ]; - $job = new \Resque\Job\Job('jobs', $payload); + $job = new Resque_Job('jobs', $payload); $worker->workingOn($job); $job = $worker->job(); @@ -190,17 +188,14 @@ class WorkerTest extends TestCase public function testWorkerErasesItsStatsWhenShutdown() { - \Resque\Resque::enqueue('jobs', '\Resque\Test\TestJob'); - \Resque\Resque::enqueue('jobs', '\Resque\Test\InvalidJob'); + Resque::enqueue('jobs', 'Test_Job'); + Resque::enqueue('jobs', 'Invalid_Job'); - $worker = new \Resque\Worker('jobs'); - $worker->setLogger(new \Resque\Log()); + $worker = new Resque_Worker('jobs'); + $worker->setLogger(new Resque_Log()); $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('failed')); } @@ -208,84 +203,87 @@ class WorkerTest extends TestCase public function testWorkerCleansUpDeadWorkersOnStartup() { // Register a good worker - $goodWorker = new \Resque\Worker('jobs'); - $goodWorker->setLogger(new \Resque\Log()); + $goodWorker = new Resque_Worker('jobs'); + $goodWorker->setLogger(new Resque_Log()); $goodWorker->registerWorker(); $workerId = explode(':', $goodWorker); // Register some bad workers - $worker = new \Resque\Worker('jobs'); - $worker->setLogger(new \Resque\Log()); + $worker = new Resque_Worker('jobs'); + $worker->setLogger(new Resque_Log()); $worker->setId($workerId[0] . ':1:jobs'); $worker->registerWorker(); - $worker = new \Resque\Worker(['high', 'low']); - $worker->setLogger(new \Resque\Log()); + $worker = new Resque_Worker(['high', 'low']); + $worker->setLogger(new Resque_Log()); $worker->setId($workerId[0] . ':2:high,low'); $worker->registerWorker(); - $this->assertEquals(3, count(\Resque\Worker::all())); + $this->assertEquals(3, count(Resque_Worker::all())); $goodWorker->pruneDeadWorkers(); // There should only be $goodWorker left now - $this->assertEquals(1, count(\Resque\Worker::all())); + $this->assertEquals(1, count(Resque_Worker::all())); } public function testDeadWorkerCleanUpDoesNotCleanUnknownWorkers() { // Register a bad worker on this machine - $worker = new \Resque\Worker('jobs'); - $worker->setLogger(new \Resque\Log()); + $worker = new Resque_Worker('jobs'); + $worker->setLogger(new Resque_Log()); $workerId = explode(':', $worker); $worker->setId($workerId[0] . ':1:jobs'); $worker->registerWorker(); // Register some other false workers - $worker = new \Resque\Worker('jobs'); - $worker->setLogger(new \Resque\Log()); + $worker = new Resque_Worker('jobs'); + $worker->setLogger(new Resque_Log()); $worker->setId('my.other.host:1:jobs'); $worker->registerWorker(); - $this->assertEquals(2, count(\Resque\Worker::all())); + $this->assertEquals(2, count(Resque_Worker::all())); $worker->pruneDeadWorkers(); // my.other.host should be left - $workers = \Resque\Worker::all(); + $workers = Resque_Worker::all(); $this->assertEquals(1, count($workers)); $this->assertEquals((string)$worker, (string)$workers[0]); } public function testWorkerFailsUncompletedJobsOnExit() { - $worker = new \Resque\Worker('jobs'); - $worker->setLogger(new \Resque\Log()); + $worker = new Resque_Worker('jobs'); + $worker->setLogger(new Resque_Log()); $worker->registerWorker(); $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->unregisterWorker(); - $this->assertEquals(1, \Resque\Stat::get('failed')); + $this->assertEquals(1, Resque_Stat::get('failed')); } public function testBlockingListPop() { - $worker = new \Resque\Worker('jobs'); - $worker->setLogger(new \Resque\Log()); + $this->markTestSkipped("Skip temporarily"); + return; + + $worker = new Resque_Worker('jobs'); + $worker->setLogger(new Resque_Log()); $worker->registerWorker(); - \Resque\Resque::enqueue('jobs', '\Resque\Test\TestJob_1'); - \Resque\Resque::enqueue('jobs', '\Resque\Test\TestJob_2'); + Resque::enqueue('jobs', 'Test_Job_1'); + Resque::enqueue('jobs', 'Test_Job_2'); $i = 1; 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) { break; diff --git a/test/bootstrap.php b/test/bootstrap.php new file mode 100644 index 0000000..a92611c --- /dev/null +++ b/test/bootstrap.php @@ -0,0 +1,150 @@ + + * @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; + } +} \ No newline at end of file diff --git a/test/misc/redis.conf b/test/misc/redis.conf new file mode 100644 index 0000000..971f66e --- /dev/null +++ b/test/misc/redis.conf @@ -0,0 +1,8 @@ +daemonize yes +pidfile ./redis.pid +port 6379 +bind 127.0.0.1 +timeout 300 +dbfilename dump.rdb +dir ./ +loglevel debug \ No newline at end of file diff --git a/tests/Resque/Tests/JobStatusTest.php b/tests/Resque/Tests/JobStatusTest.php deleted file mode 100644 index a7185cc..0000000 --- a/tests/Resque/Tests/JobStatusTest.php +++ /dev/null @@ -1,110 +0,0 @@ - - * @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()); - } -} \ No newline at end of file diff --git a/tests/Resque/Tests/JobTest.php b/tests/Resque/Tests/JobTest.php deleted file mode 100644 index f6c261f..0000000 --- a/tests/Resque/Tests/JobTest.php +++ /dev/null @@ -1,431 +0,0 @@ - - * @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(); - } -} diff --git a/tests/bootstrap.php b/tests/bootstrap.php deleted file mode 100644 index cf26e96..0000000 --- a/tests/bootstrap.php +++ /dev/null @@ -1,102 +0,0 @@ - - * @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; - } -} \ No newline at end of file