Added Beanstalkd producer/worker

This commit is contained in:
Frederic Guillot 2016-05-01 22:03:21 -04:00
parent d2e0edbc2e
commit b2edaad23d
58 changed files with 3312 additions and 3 deletions

View File

@ -42,6 +42,10 @@ defined('RULES_DIRECTORY') or define('RULES_DIRECTORY', ROOT_DIRECTORY.DIRECTORY
defined('ENABLE_HSTS') or define('ENABLE_HSTS', true);
defined('BEANSTALKD_HOST') or define('BEANSTALKD_HOST', '127.0.0.1');
defined('BEANSTALKD_QUEUE') or define('BEANSTALKD_QUEUE', 'feeds');
defined('BEANSTALKD_TTL') or define('BEANSTALKD_TTL', 120);
require __DIR__.'/check_setup.php';
PicoDb\Database::setInstance('db', function() {

View File

@ -15,7 +15,8 @@
"fguillot/simple-validator": "v1.0.0",
"fguillot/json-rpc": "v1.0.2",
"fguillot/picodb": "v1.0.2",
"fguillot/picofeed": "v0.1.23"
"fguillot/picofeed": "v0.1.23",
"pda/pheanstalk": "v3.1.0"
},
"require-dev": {
"phpunit/phpunit": "4.8.3",

View File

@ -3,7 +3,6 @@
require __DIR__.'/common.php';
if (php_sapi_name() === 'cli') {
$options = getopt('', array(
'limit::',
'call-interval::',
@ -12,7 +11,6 @@ if (php_sapi_name() === 'cli') {
));
}
else {
$options = $_GET;
}

13
producer.php Normal file
View File

@ -0,0 +1,13 @@
<?php
use Pheanstalk\Pheanstalk;
require __DIR__.'/common.php';
$connection = new Pheanstalk(BEANSTALKD_HOST);
foreach (Model\Feed\get_ids() as $feed_id) {
$connection
->useTube(BEANSTALKD_QUEUE)
->put($feed_id, Pheanstalk::DEFAULT_PRIORITY, Pheanstalk::DEFAULT_DELAY, BEANSTALKD_TTL);
}

View File

@ -15,6 +15,50 @@ return array(
'JsonRPC\\ResponseException' => $vendorDir . '/fguillot/json-rpc/src/JsonRPC/ResponseException.php',
'JsonRPC\\Server' => $vendorDir . '/fguillot/json-rpc/src/JsonRPC/Server.php',
'JsonRPC\\ServerErrorException' => $vendorDir . '/fguillot/json-rpc/src/JsonRPC/Client.php',
'Pheanstalk\\Command' => $vendorDir . '/pda/pheanstalk/src/Command.php',
'Pheanstalk\\Command\\AbstractCommand' => $vendorDir . '/pda/pheanstalk/src/Command/AbstractCommand.php',
'Pheanstalk\\Command\\BuryCommand' => $vendorDir . '/pda/pheanstalk/src/Command/BuryCommand.php',
'Pheanstalk\\Command\\DeleteCommand' => $vendorDir . '/pda/pheanstalk/src/Command/DeleteCommand.php',
'Pheanstalk\\Command\\IgnoreCommand' => $vendorDir . '/pda/pheanstalk/src/Command/IgnoreCommand.php',
'Pheanstalk\\Command\\KickCommand' => $vendorDir . '/pda/pheanstalk/src/Command/KickCommand.php',
'Pheanstalk\\Command\\KickJobCommand' => $vendorDir . '/pda/pheanstalk/src/Command/KickJobCommand.php',
'Pheanstalk\\Command\\ListTubeUsedCommand' => $vendorDir . '/pda/pheanstalk/src/Command/ListTubeUsedCommand.php',
'Pheanstalk\\Command\\ListTubesCommand' => $vendorDir . '/pda/pheanstalk/src/Command/ListTubesCommand.php',
'Pheanstalk\\Command\\ListTubesWatchedCommand' => $vendorDir . '/pda/pheanstalk/src/Command/ListTubesWatchedCommand.php',
'Pheanstalk\\Command\\PauseTubeCommand' => $vendorDir . '/pda/pheanstalk/src/Command/PauseTubeCommand.php',
'Pheanstalk\\Command\\PeekCommand' => $vendorDir . '/pda/pheanstalk/src/Command/PeekCommand.php',
'Pheanstalk\\Command\\PutCommand' => $vendorDir . '/pda/pheanstalk/src/Command/PutCommand.php',
'Pheanstalk\\Command\\ReleaseCommand' => $vendorDir . '/pda/pheanstalk/src/Command/ReleaseCommand.php',
'Pheanstalk\\Command\\ReserveCommand' => $vendorDir . '/pda/pheanstalk/src/Command/ReserveCommand.php',
'Pheanstalk\\Command\\StatsCommand' => $vendorDir . '/pda/pheanstalk/src/Command/StatsCommand.php',
'Pheanstalk\\Command\\StatsJobCommand' => $vendorDir . '/pda/pheanstalk/src/Command/StatsJobCommand.php',
'Pheanstalk\\Command\\StatsTubeCommand' => $vendorDir . '/pda/pheanstalk/src/Command/StatsTubeCommand.php',
'Pheanstalk\\Command\\TouchCommand' => $vendorDir . '/pda/pheanstalk/src/Command/TouchCommand.php',
'Pheanstalk\\Command\\UseCommand' => $vendorDir . '/pda/pheanstalk/src/Command/UseCommand.php',
'Pheanstalk\\Command\\WatchCommand' => $vendorDir . '/pda/pheanstalk/src/Command/WatchCommand.php',
'Pheanstalk\\Connection' => $vendorDir . '/pda/pheanstalk/src/Connection.php',
'Pheanstalk\\Exception' => $vendorDir . '/pda/pheanstalk/src/Exception.php',
'Pheanstalk\\Exception\\ClientException' => $vendorDir . '/pda/pheanstalk/src/Exception/ClientException.php',
'Pheanstalk\\Exception\\CommandException' => $vendorDir . '/pda/pheanstalk/src/Exception/CommandException.php',
'Pheanstalk\\Exception\\ConnectionException' => $vendorDir . '/pda/pheanstalk/src/Exception/ConnectionException.php',
'Pheanstalk\\Exception\\ServerBadFormatException' => $vendorDir . '/pda/pheanstalk/src/Exception/ServerBadFormatException.php',
'Pheanstalk\\Exception\\ServerDrainingException' => $vendorDir . '/pda/pheanstalk/src/Exception/ServerDrainingException.php',
'Pheanstalk\\Exception\\ServerException' => $vendorDir . '/pda/pheanstalk/src/Exception/ServerException.php',
'Pheanstalk\\Exception\\ServerInternalErrorException' => $vendorDir . '/pda/pheanstalk/src/Exception/ServerInternalErrorException.php',
'Pheanstalk\\Exception\\ServerOutOfMemoryException' => $vendorDir . '/pda/pheanstalk/src/Exception/ServerOutOfMemoryException.php',
'Pheanstalk\\Exception\\ServerUnknownCommandException' => $vendorDir . '/pda/pheanstalk/src/Exception/ServerUnknownCommandException.php',
'Pheanstalk\\Exception\\SocketException' => $vendorDir . '/pda/pheanstalk/src/Exception/SocketException.php',
'Pheanstalk\\Job' => $vendorDir . '/pda/pheanstalk/src/Job.php',
'Pheanstalk\\Pheanstalk' => $vendorDir . '/pda/pheanstalk/src/Pheanstalk.php',
'Pheanstalk\\PheanstalkInterface' => $vendorDir . '/pda/pheanstalk/src/PheanstalkInterface.php',
'Pheanstalk\\Response' => $vendorDir . '/pda/pheanstalk/src/Response.php',
'Pheanstalk\\ResponseParser' => $vendorDir . '/pda/pheanstalk/src/ResponseParser.php',
'Pheanstalk\\Response\\ArrayResponse' => $vendorDir . '/pda/pheanstalk/src/Response/ArrayResponse.php',
'Pheanstalk\\Socket' => $vendorDir . '/pda/pheanstalk/src/Socket.php',
'Pheanstalk\\Socket\\NativeSocket' => $vendorDir . '/pda/pheanstalk/src/Socket/NativeSocket.php',
'Pheanstalk\\Socket\\StreamFunctions' => $vendorDir . '/pda/pheanstalk/src/Socket/StreamFunctions.php',
'Pheanstalk\\Socket\\WriteHistory' => $vendorDir . '/pda/pheanstalk/src/Socket/WriteHistory.php',
'Pheanstalk\\YamlResponseParser' => $vendorDir . '/pda/pheanstalk/src/YamlResponseParser.php',
'PicoDb\\Condition' => $vendorDir . '/fguillot/picodb/lib/PicoDb/Condition.php',
'PicoDb\\Database' => $vendorDir . '/fguillot/picodb/lib/PicoDb/Database.php',
'PicoDb\\Driver\\Base' => $vendorDir . '/fguillot/picodb/lib/PicoDb/Driver/Base.php',

View File

@ -6,4 +6,5 @@ $vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
return array(
'Pheanstalk\\' => array($vendorDir . '/pda/pheanstalk/src'),
);

View File

@ -210,5 +210,57 @@
],
"description": "Modern library to handle RSS/Atom feeds",
"homepage": "https://github.com/fguillot/picoFeed"
},
{
"name": "pda/pheanstalk",
"version": "v3.1.0",
"version_normalized": "3.1.0.0",
"source": {
"type": "git",
"url": "https://github.com/pda/pheanstalk.git",
"reference": "430e77c551479aad0c6ada0450ee844cf656a18b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pda/pheanstalk/zipball/430e77c551479aad0c6ada0450ee844cf656a18b",
"reference": "430e77c551479aad0c6ada0450ee844cf656a18b",
"shasum": ""
},
"require": {
"php": ">=5.3.0"
},
"require-dev": {
"phpunit/phpunit": "~4.0"
},
"time": "2015-08-07 21:42:41",
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.0-dev"
}
},
"installation-source": "dist",
"autoload": {
"psr-4": {
"Pheanstalk\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Paul Annesley",
"email": "paul@annesley.cc",
"homepage": "http://paul.annesley.cc/",
"role": "Developer"
}
],
"description": "PHP client for beanstalkd queue",
"homepage": "https://github.com/pda/pheanstalk",
"keywords": [
"beanstalkd"
]
}
]

4
vendor/pda/pheanstalk/.gitattributes vendored Normal file
View File

@ -0,0 +1,4 @@
tests/ export-ignore
phpunit.xml.dist export-ignore
doc/ export-ignore
.travis.yml export-ignore

8
vendor/pda/pheanstalk/.gitignore vendored Normal file
View File

@ -0,0 +1,8 @@
pheanstalk.phar
# Composer lock file; do not commit, this is a library not an app.
# See: http://yehudakatz.com/2010/12/16/clarifying-the-roles-of-the-gemspec-and-gemfile/
/composer.lock
# Composer installs dependencies here.
vendor/

22
vendor/pda/pheanstalk/LICENSE vendored Normal file
View File

@ -0,0 +1,22 @@
The MIT License
Copyright (c) 20082015 Paul Annesley
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

135
vendor/pda/pheanstalk/README.md vendored Normal file
View File

@ -0,0 +1,135 @@
Pheanstalk
==========
[![Build Status](https://travis-ci.org/pda/pheanstalk.png?branch=master)](https://travis-ci.org/pda/pheanstalk)
Pheanstalk is a pure PHP 5.3+ client for the [beanstalkd workqueue][1]. It has
been actively developed, and used in production by many, since late 2008.
Created by [Paul Annesley][2], Pheanstalk is rigorously unit tested and written
using encapsulated, maintainable object oriented design. Community feedback,
bug reports and patches has led to a stable 1.0 release in 2010, a 2.0 release
in 2013, and a 3.0 release in 2014.
Pheanstalk 3.0 introduces PHP namespaces, PSR-1 and PSR-2 coding standards,
and PSR-4 autoloader standard.
beanstalkd up to the latest version 1.4 is supported. All commands and
responses specified in the [protocol documentation][3] for beanstalkd 1.3 are
implemented.
[1]: http://xph.us/software/beanstalkd/
[2]: http://paul.annesley.cc/
[3]: http://github.com/kr/beanstalkd/tree/v1.3/doc/protocol.txt?raw=true
Installation with Composer
-------------
Install pheanstalk as a dependency with composer:
```bash
composer require pda/pheanstalk
```
Usage Example
-------------
```php
<?php
// Hopefully you're using Composer autoloading.
use Pheanstalk\Pheanstalk;
$pheanstalk = new Pheanstalk('127.0.0.1');
// ----------------------------------------
// producer (queues jobs)
$pheanstalk
->useTube('testtube')
->put("job payload goes here\n");
// ----------------------------------------
// worker (performs jobs)
$job = $pheanstalk
->watch('testtube')
->ignore('default')
->reserve();
echo $job->getData();
$pheanstalk->delete($job);
// ----------------------------------------
// check server availability
$pheanstalk->getConnection()->isServiceListening(); // true or false
```
Running the tests
-----------------
There is a section of the test suite which depends on a running beanstalkd
at 127.0.0.1:11300, which was previously opt-in via `--with-server`.
Since porting to PHPUnit, all tests are run at once. Feel free to submit
a pull request to rectify this.
```
# ensure you have Composer set up
$ wget http://getcomposer.org/composer.phar
$ php composer.phar install
# ensure you have PHPUnit
$ composer install --dev
$ ./vendor/bin/phpunit
PHPUnit 4.0.19 by Sebastian Bergmann.
Configuration read from /Users/pda/code/pheanstalk/phpunit.xml.dist
................................................................. 65 / 83 ( 78%)
..................
Time: 239 ms, Memory: 6.00Mb
OK (83 tests, 378 assertions)
```
Contributors
------------
* [Paul Annesley](https://github.com/pda)
* [Lachlan Donald](https://github.com/lox)
* [Joakim Bick](https://github.com/minimoe)
* [Vyacheslav](https://github.com/SlNPacifist)
* [leprechaun](https://github.com/leprechaun)
* [Peter McArthur](https://github.com/ptrmcrthr)
* [robbiehudson](https://github.com/robbiehudson)
* [Geoff Catlin](https://github.com/gcatlin)
* [Steven Lewis](https://github.com/srjlewis)
* [Lars Yencken](https://github.com/larsyencken)
* [Josh Butts](https://github.com/jimbojsb)
* [Henry Smith](https://github.com/h2s)
* [Javier Spagnoletti](https://github.com/phansys)
* [Graham Campbell](https://github.com/GrahamCampbell)
* [Thomas Tourlourat](https://github.com/armetiz)
* [Matthieu Napoli](https://github.com/mnapoli)
* [Christoph](https://github.com/xrstf)
* [James Hamilton](https://github.com/mrjameshamilton)
* [Hannes Van De Vreken](https://github.com/hannesvdvreken)
* [Yaniv Davidovitch](https://github.com/YanivD)
* .. [more?](https://github.com/pda/pheanstalk/contributors) Let me know if you're missing.
License
-------
© Paul Annesley
Released under the [The MIT License](http://www.opensource.org/licenses/mit-license.php)

32
vendor/pda/pheanstalk/composer.json vendored Normal file
View File

@ -0,0 +1,32 @@
{
"name": "pda/pheanstalk",
"type": "library",
"description": "PHP client for beanstalkd queue",
"keywords": ["beanstalkd"],
"homepage": "https://github.com/pda/pheanstalk",
"license": "MIT",
"authors": [
{
"name": "Paul Annesley",
"email": "paul@annesley.cc",
"homepage": "http://paul.annesley.cc/",
"role": "Developer"
}
],
"require": {
"php": ">=5.3.0"
},
"require-dev": {
"phpunit/phpunit": "~4.0"
},
"autoload": {
"psr-4": {
"Pheanstalk\\": "src/"
}
},
"extra": {
"branch-alias": {
"dev-master": "3.0-dev"
}
}
}

57
vendor/pda/pheanstalk/scripts/build_phar.php vendored Executable file
View File

@ -0,0 +1,57 @@
#!/usr/bin/env php
<?php
define('BASE_DIR', realpath(__DIR__ . '/..'));
define('PHAR_FILENAME', 'pheanstalk.phar');
define('PHAR_FULLPATH', BASE_DIR . '/' . PHAR_FILENAME);
// ----------------------------------------
reexecute_if_phar_readonly($argv);
delete_existing_pheanstalk_phar();
build_pheanstalk_phar();
verify_pheanstalk_phar();
exit(0);
// ----------------------------------------
// See: http://www.php.net/manual/en/phar.configuration.php#ini.phar.readonly
function reexecute_if_phar_readonly($argv)
{
if (ini_get('phar.readonly') && !in_array('--ignore-readonly', $argv)) {
$command = sprintf(
'php -d phar.readonly=0 %s --ignore-readonly',
implode($argv, ' ')
);
echo "Phar configured readonly in php.ini; attempting to re-execute:\n";
echo "$command\n";
passthru($command, $exitStatus);
exit($exitStatus);
}
}
function delete_existing_pheanstalk_phar()
{
if (file_exists(PHAR_FULLPATH)) {
printf("- Deleting existing %s\n", PHAR_FILENAME);
unlink(PHAR_FULLPATH);
}
}
function build_pheanstalk_phar()
{
printf("- Building %s from %s\n", PHAR_FILENAME, BASE_DIR);
$phar = new Phar(PHAR_FULLPATH);
$phar->buildFromDirectory(BASE_DIR);
$phar->setStub(
$phar->createDefaultStub("vendor/autoload.php")
);
}
function verify_pheanstalk_phar()
{
$phar = new Phar(PHAR_FULLPATH);
printf("- %s built with %d files.\n", PHAR_FILENAME, $phar->count());
}

61
vendor/pda/pheanstalk/src/Command.php vendored Normal file
View File

@ -0,0 +1,61 @@
<?php
namespace Pheanstalk;
/**
* A command to be sent to the beanstalkd server, and response processing logic
*
* @author Paul Annesley
* @package Pheanstalk
* @license http://www.opensource.org/licenses/mit-license.php
*/
interface Command
{
const COMMAND_PUT = 'put';
const COMMAND_USE = 'use';
const COMMAND_RESERVE = 'reserve';
const COMMAND_DELETE = 'delete';
const COMMAND_RELEASE = 'release';
const COMMAND_BURY = 'bury';
const COMMAND_WATCH = 'watch';
const COMMAND_IGNORE = 'ignore';
const COMMAND_PEEK = 'peek';
const COMMAND_KICK = 'kick';
const COMMAND_STATS_JOB = 'stats-job';
const COMMAND_STATS = 'stats';
const COMMAND_LIST_TUBES = 'list-tubes';
const COMMAND_LIST_TUBE_USED = 'list-tube-used';
const COMMAND_LIST_TUBES_WATCHED = 'list-tubes-watched';
/**
* The command line, without trailing CRLF
* @return string
*/
public function getCommandLine();
/**
* Whether the command is followed by data
* @return boolean
*/
public function hasData();
/**
* The binary data to follow the command
* @return string
* @throws Exception\CommandException If command has no data
*/
public function getData();
/**
* The length of the binary data in bytes
* @return int
* @throws Exception\CommandException If command has no data
*/
public function getDataLength();
/**
* The response parser for the command.
* @return ResponseParser
*/
public function getResponseParser();
}

View File

@ -0,0 +1,74 @@
<?php
namespace Pheanstalk\Command;
use Pheanstalk\Command;
use Pheanstalk\Response;
/**
* Common functionality for Command implementations.
*
* @author Paul Annesley
* @package Pheanstalk
* @license http://www.opensource.org/licenses/mit-license.php
*/
abstract class AbstractCommand
implements Command
{
/* (non-phpdoc)
* @see Command::hasData()
*/
public function hasData()
{
return false;
}
/* (non-phpdoc)
* @see Command::getData()
*/
public function getData()
{
throw new Exception\CommandException('Command has no data');
}
/* (non-phpdoc)
* @see Command::getDataLength()
*/
public function getDataLength()
{
throw new Exception\CommandException('Command has no data');
}
/* (non-phpdoc)
* @see Command::getResponseParser()
*/
public function getResponseParser()
{
// concrete implementation must either:
// a) implement ResponseParser
// b) override this getResponseParser method
return $this;
}
/**
* The string representation of the object.
* @return string
*/
public function __toString()
{
return $this->getCommandLine();
}
// ----------------------------------------
// protected
/**
* Creates a Response for the given data
* @param array
* @return object Response
*/
protected function _createResponse($name, $data = array())
{
return new Response\ArrayResponse($name, $data);
}
}

View File

@ -0,0 +1,62 @@
<?php
namespace Pheanstalk\Command;
use Pheanstalk\Exception;
use Pheanstalk\Response;
/**
* The 'bury' command.
* Puts a job into a 'buried' state, revived only by 'kick' command.
*
* @author Paul Annesley
* @package Pheanstalk
* @license http://www.opensource.org/licenses/mit-license.php
*/
class BuryCommand
extends AbstractCommand
implements \Pheanstalk\ResponseParser
{
private $_job;
private $_priority;
/**
* @param object $job Job
* @param int $priority From 0 (most urgent) to 0xFFFFFFFF (least urgent)
*/
public function __construct($job, $priority)
{
$this->_job = $job;
$this->_priority = $priority;
}
/* (non-phpdoc)
* @see Command::getCommandLine()
*/
public function getCommandLine()
{
return sprintf(
'bury %u %u',
$this->_job->getId(),
$this->_priority
);
}
/* (non-phpdoc)
* @see ResponseParser::parseResponse()
*/
public function parseResponse($responseLine, $responseData)
{
if ($responseLine == Response::RESPONSE_NOT_FOUND) {
throw new Exception\ServerException(sprintf(
'%s: Job %u is not reserved or does not exist.',
$responseLine,
$this->_job->getId()
));
} elseif ($responseLine == Response::RESPONSE_BURIED) {
return $this->_createResponse(Response::RESPONSE_BURIED);
} else {
throw new Exception('Unhandled response: '.$responseLine);
}
}
}

View File

@ -0,0 +1,53 @@
<?php
namespace Pheanstalk\Command;
use Pheanstalk\Exception;
use Pheanstalk\Response;
/**
* The 'delete' command.
* Permanently deletes an already-reserved job.
*
* @author Paul Annesley
* @package Pheanstalk
* @license http://www.opensource.org/licenses/mit-license.php
*/
class DeleteCommand
extends AbstractCommand
implements \Pheanstalk\ResponseParser
{
private $_job;
/**
* @param object $job Job
*/
public function __construct($job)
{
$this->_job = $job;
}
/* (non-phpdoc)
* @see Command::getCommandLine()
*/
public function getCommandLine()
{
return 'delete '.$this->_job->getId();
}
/* (non-phpdoc)
* @see ResponseParser::parseResponse()
*/
public function parseResponse($responseLine, $responseData)
{
if ($responseLine == Response::RESPONSE_NOT_FOUND) {
throw new Exception\ServerException(sprintf(
'Cannot delete job %u: %s',
$this->_job->getId(),
$responseLine
));
}
return $this->_createResponse($responseLine);
}
}

View File

@ -0,0 +1,54 @@
<?php
namespace Pheanstalk\Command;
use Pheanstalk\Exception;
use Pheanstalk\Response;
/**
* The 'ignore' command.
* Removes a tube from the watch list to reserve jobs from.
*
* @author Paul Annesley
* @package Pheanstalk
* @license http://www.opensource.org/licenses/mit-license.php
*/
class IgnoreCommand
extends AbstractCommand
implements \Pheanstalk\ResponseParser
{
private $_tube;
/**
* @param string $tube
*/
public function __construct($tube)
{
$this->_tube = $tube;
}
/* (non-phpdoc)
* @see Command::getCommandLine()
*/
public function getCommandLine()
{
return 'ignore '.$this->_tube;
}
/* (non-phpdoc)
* @see ResponseParser::parseResponse()
*/
public function parseResponse($responseLine, $responseData)
{
if (preg_match('#^WATCHING (\d+)$#', $responseLine, $matches)) {
return $this->_createResponse('WATCHING', array(
'count' => (int) $matches[1]
));
} elseif ($responseLine == Response::RESPONSE_NOT_IGNORED) {
throw new Exception\ServerException($responseLine .
': cannot ignore last tube in watchlist');
} else {
throw new Exception('Unhandled response: '.$responseLine);
}
}
}

View File

@ -0,0 +1,48 @@
<?php
namespace Pheanstalk\Command;
/**
* The 'kick' command.
* Kicks buried or delayed jobs into a 'ready' state.
* If there are buried jobs, it will kick up to $max of them.
* Otherwise, it will kick up to $max delayed jobs.
*
* @author Paul Annesley
* @package Pheanstalk
* @license http://www.opensource.org/licenses/mit-license.php
*/
class KickCommand
extends AbstractCommand
implements \Pheanstalk\ResponseParser
{
private $_max;
/**
* @param int $max The maximum number of jobs to kick
*/
public function __construct($max)
{
$this->_max = (int) $max;
}
/* (non-phpdoc)
* @see Command::getCommandLine()
*/
public function getCommandLine()
{
return 'kick '.$this->_max;
}
/* (non-phpdoc)
* @see ResponseParser::parseResponse()
*/
public function parseResponse($responseLine, $responseData)
{
list($code, $count) = explode(' ', $responseLine);
return $this->_createResponse($code, array(
'kicked' => (int) $count,
));
}
}

View File

@ -0,0 +1,59 @@
<?php
namespace Pheanstalk\Command;
use Pheanstalk\Exception;
use Pheanstalk\Response;
/**
* The 'kick-job' command.
* Kicks a specific buried or delayed job into a 'ready' state.
*
* A variant of kick that operates with a single job. If the given job
* exists and is in a buried or delayed state, it will be moved to the
* ready queue of the the same tube where it currently belongs.
*
* @author Matthieu Napoli
* @package Pheanstalk
* @license http://www.opensource.org/licenses/mit-license.php
*/
class KickJobCommand
extends AbstractCommand
implements \Pheanstalk\ResponseParser
{
private $_job;
/**
* @param Job $job Pheanstalk job
*/
public function __construct($job)
{
$this->_job = $job;
}
/* (non-phpdoc)
* @see Command::getCommandLine()
*/
public function getCommandLine()
{
return 'kick-job '.$this->_job->getId();
}
/* (non-phpdoc)
* @see ResponseParser::parseResponse()
*/
public function parseResponse($responseLine, $responseData)
{
if ($responseLine == Response::RESPONSE_NOT_FOUND) {
throw new Exception\ServerException(sprintf(
'%s: Job %d does not exist or is not in a kickable state.',
$responseLine,
$this->_job->getId()
));
} elseif ($responseLine == Response::RESPONSE_KICKED) {
return $this->_createResponse(Response::RESPONSE_KICKED);
} else {
throw new Exception('Unhandled response: '.$responseLine);
}
}
}

View File

@ -0,0 +1,34 @@
<?php
namespace Pheanstalk\Command;
/**
* The 'list-tube-used' command.
* Returns the tube currently being used by the client.
*
* @author Paul Annesley
* @package Pheanstalk
* @license http://www.opensource.org/licenses/mit-license.php
*/
class ListTubeUsedCommand
extends AbstractCommand
implements \Pheanstalk\ResponseParser
{
/* (non-phpdoc)
* @see Command::getCommandLine()
*/
public function getCommandLine()
{
return 'list-tube-used';
}
/* (non-phpdoc)
* @see ResponseParser::parseResponse()
*/
public function parseResponse($responseLine, $responseData)
{
return $this->_createResponse('USING', array(
'tube' => preg_replace('#^USING (.+)$#', '$1', $responseLine)
));
}
}

View File

@ -0,0 +1,35 @@
<?php
namespace Pheanstalk\Command;
use Pheanstalk\YamlResponseParser;
/**
* The 'list-tubes' command.
* List all existing tubes.
*
* @author Paul Annesley
* @package Pheanstalk
* @license http://www.opensource.org/licenses/mit-license.php
*/
class ListTubesCommand
extends AbstractCommand
{
/* (non-phpdoc)
* @see Command::getCommandLine()
*/
public function getCommandLine()
{
return 'list-tubes';
}
/* (non-phpdoc)
* @see Command::getResponseParser()
*/
public function getResponseParser()
{
return new YamlResponseParser(
YamlResponseParser::MODE_LIST
);
}
}

View File

@ -0,0 +1,35 @@
<?php
namespace Pheanstalk\Command;
use Pheanstalk\YamlResponseParser;
/**
* The 'list-tubes-watched' command.
* Lists the tubes on the watchlist.
*
* @author Paul Annesley
* @package Pheanstalk
* @license http://www.opensource.org/licenses/mit-license.php
*/
class ListTubesWatchedCommand
extends AbstractCommand
{
/* (non-phpdoc)
* @see Command::getCommandLine()
*/
public function getCommandLine()
{
return 'list-tubes-watched';
}
/* (non-phpdoc)
* @see Command::getResponseParser()
*/
public function getResponseParser()
{
return new YamlResponseParser(
YamlResponseParser::MODE_LIST
);
}
}

View File

@ -0,0 +1,62 @@
<?php
namespace Pheanstalk\Command;
use Pheanstalk\Exception;
use Pheanstalk\Response;
/**
* The 'pause-tube' command.
* Temporarily prevent jobs being reserved from the given tube.
*
* @author Paul Annesley
* @package Pheanstalk
* @license http://www.opensource.org/licenses/mit-license.php
*/
class PauseTubeCommand
extends AbstractCommand
implements \Pheanstalk\ResponseParser
{
private $_tube;
private $_delay;
/**
* @param string $tube The tube to pause
* @param int $delay Seconds before jobs may be reserved from this queue.
*/
public function __construct($tube, $delay)
{
$this->_tube = $tube;
$this->_delay = $delay;
}
/* (non-phpdoc)
* @see Command::getCommandLine()
*/
public function getCommandLine()
{
return sprintf(
'pause-tube %s %u',
$this->_tube,
$this->_delay
);
}
/* (non-phpdoc)
* @see ResponseParser::parseResponse()
*/
public function parseResponse($responseLine, $responseData)
{
if ($responseLine == Response::RESPONSE_NOT_FOUND) {
throw new Exception\ServerException(sprintf(
'%s: tube %s does not exist.',
$responseLine,
$this->_tube
));
} elseif ($responseLine == Response::RESPONSE_PAUSED) {
return $this->_createResponse(Response::RESPONSE_PAUSED);
} else {
throw new Exception('Unhandled response: '.$responseLine);
}
}
}

View File

@ -0,0 +1,93 @@
<?php
namespace Pheanstalk\Command;
use Pheanstalk\Exception;
use Pheanstalk\Response;
/**
* The 'peek', 'peek-ready', 'peek-delayed' and 'peek-buried' commands.
*
* The peek commands let the client inspect a job in the system. There are four
* variations. All but the first (peek) operate only on the currently used tube.
*
* @author Paul Annesley
* @package Pheanstalk
* @license http://www.opensource.org/licenses/mit-license.php
*/
class PeekCommand
extends AbstractCommand
implements \Pheanstalk\ResponseParser
{
const TYPE_ID = 'id';
const TYPE_READY = 'ready';
const TYPE_DELAYED = 'delayed';
const TYPE_BURIED = 'buried';
private $_subcommands = array(
self::TYPE_READY,
self::TYPE_DELAYED,
self::TYPE_BURIED,
);
private $_subcommand;
private $_jobId;
/**
* @param mixed $peekSubject Job ID or self::TYPE_*
*/
public function __construct($peekSubject)
{
if (is_int($peekSubject) || ctype_digit($peekSubject)) {
$this->_jobId = $peekSubject;
} elseif (in_array($peekSubject, $this->_subcommands)) {
$this->_subcommand = $peekSubject;
} else {
throw new Exception\CommandException(sprintf(
'Invalid peek subject: %s', $peekSubject
));
}
}
/* (non-phpdoc)
* @see Command::getCommandLine()
*/
public function getCommandLine()
{
return isset($this->_jobId) ?
sprintf('peek %u', $this->_jobId) :
sprintf('peek-%s', $this->_subcommand);
}
/* (non-phpdoc)
* @see ResponseParser::parseResponse()
*/
public function parseResponse($responseLine, $responseData)
{
if ($responseLine == Response::RESPONSE_NOT_FOUND) {
if (isset($this->_jobId)) {
$message = sprintf(
'%s: Job %u does not exist.',
$responseLine,
$this->_jobId
);
} else {
$message = sprintf(
"%s: There are no jobs in the '%s' status",
$responseLine,
$this->_subcommand
);
}
throw new Exception\ServerException($message);
} elseif (preg_match('#^FOUND (\d+) \d+$#', $responseLine, $matches)) {
return $this->_createResponse(
Response::RESPONSE_FOUND,
array(
'id' => (int) $matches[1],
'jobdata' => $responseData,
)
);
}
}
}

View File

@ -0,0 +1,113 @@
<?php
namespace Pheanstalk\Command;
use Pheanstalk\Exception;
/**
* The 'put' command.
* Inserts a job into the client's currently used tube.
* @see UseCommand
*
* @author Paul Annesley
* @package Pheanstalk
* @license http://www.opensource.org/licenses/mit-license.php
*/
class PutCommand
extends AbstractCommand
implements \Pheanstalk\ResponseParser
{
private $_data;
private $_priority;
private $_delay;
private $_ttr;
/**
* Puts a job on the queue
* @param string $data The job data
* @param int $priority From 0 (most urgent) to 0xFFFFFFFF (least urgent)
* @param int $delay Seconds to wait before job becomes ready
* @param int $ttr Time To Run: seconds a job can be reserved for
*/
public function __construct($data, $priority, $delay, $ttr)
{
$this->_data = $data;
$this->_priority = $priority;
$this->_delay = $delay;
$this->_ttr = $ttr;
}
/* (non-phpdoc)
* @see Command::getCommandLine()
*/
public function getCommandLine()
{
return sprintf(
'put %u %u %u %u',
$this->_priority,
$this->_delay,
$this->_ttr,
$this->getDataLength()
);
}
/* (non-phpdoc)
* @see Command::hasData()
*/
public function hasData()
{
return true;
}
/* (non-phpdoc)
* @see Command::getData()
*/
public function getData()
{
return $this->_data;
}
/* (non-phpdoc)
* @see Command::getDataLength()
*/
public function getDataLength()
{
if (function_exists('mb_strlen')) {
return mb_strlen($this->_data, "latin1");
} else {
return strlen($this->_data);
}
}
/* (non-phpdoc)
* @see ResponseParser::parseResponse()
*/
public function parseResponse($responseLine, $responseData)
{
if (preg_match('#^INSERTED (\d+)$#', $responseLine, $matches)) {
return $this->_createResponse('INSERTED', array(
'id' => (int) $matches[1]
));
} elseif (preg_match('#^BURIED (\d)+$#', $responseLine, $matches)) {
throw new Exception(sprintf(
'%s: server ran out of memory trying to grow the priority queue data structure.',
$responseLine
));
} elseif (preg_match('#^JOB_TOO_BIG$#', $responseLine)) {
throw new Exception(sprintf(
'%s: job data exceeds server-enforced limit',
$responseLine
));
} elseif (preg_match('#^EXPECTED_CRLF#', $responseLine)) {
throw new Exception(sprintf(
'%s: CRLF expected',
$responseLine
));
} else {
throw new Exception(sprintf(
'Unhandled response: %s',
$responseLine
));
}
}
}

View File

@ -0,0 +1,72 @@
<?php
namespace Pheanstalk\Command;
use Pheanstalk\Exception;
use Pheanstalk\Response;
/**
* The 'release' command.
* Releases a reserved job back onto the ready queue.
*
* @author Paul Annesley
* @package Pheanstalk
* @license http://www.opensource.org/licenses/mit-license.php
*/
class ReleaseCommand
extends AbstractCommand
implements \Pheanstalk\ResponseParser
{
private $_job;
private $_priority;
private $_delay;
/**
* @param object $job Job
* @param int $priority From 0 (most urgent) to 0xFFFFFFFF (least urgent)
* @param int $delay Seconds to wait before job becomes ready
*/
public function __construct($job, $priority, $delay)
{
$this->_job = $job;
$this->_priority = $priority;
$this->_delay = $delay;
}
/* (non-phpdoc)
* @see Command::getCommandLine()
*/
public function getCommandLine()
{
return sprintf(
'release %u %u %u',
$this->_job->getId(),
$this->_priority,
$this->_delay
);
}
/* (non-phpdoc)
* @see ResponseParser::parseResponse()
*/
public function parseResponse($responseLine, $responseData)
{
if ($responseLine == Response::RESPONSE_BURIED) {
throw new Exception\ServerException(sprintf(
'Job %u %s: out of memory trying to grow data structure',
$this->_job->getId(),
$responseLine
));
}
if ($responseLine == Response::RESPONSE_NOT_FOUND) {
throw new Exception\ServerException(sprintf(
'Job %u %s: does not exist or is not reserved by client',
$this->_job->getId(),
$responseLine
));
}
return $this->_createResponse($responseLine);
}
}

View File

@ -0,0 +1,62 @@
<?php
namespace Pheanstalk\Command;
use Pheanstalk\Response;
/**
* The 'reserve' command.
* Reserves/locks a ready job in a watched tube.
*
* @author Paul Annesley
* @package Pheanstalk
* @license http://www.opensource.org/licenses/mit-license.php
*/
class ReserveCommand
extends AbstractCommand
implements \Pheanstalk\ResponseParser
{
private $_timeout;
/**
* A timeout value of 0 will cause the server to immediately return either a
* response or TIMED_OUT. A positive value of timeout will limit the amount of
* time the client will block on the reserve request until a job becomes
* available.
*
* @param int $timeout
*/
public function __construct($timeout = null)
{
$this->_timeout = $timeout;
}
/* (non-phpdoc)
* @see Command::getCommandLine()
*/
public function getCommandLine()
{
return isset($this->_timeout) ?
sprintf('reserve-with-timeout %s', $this->_timeout) :
'reserve';
}
/* (non-phpdoc)
* @see ResponseParser::parseResponse()
*/
public function parseResponse($responseLine, $responseData)
{
if ($responseLine === Response::RESPONSE_DEADLINE_SOON ||
$responseLine === Response::RESPONSE_TIMED_OUT)
{
return $this->_createResponse($responseLine);
}
list($code, $id) = explode(' ', $responseLine);
return $this->_createResponse($code, array(
'id' => (int) $id,
'jobdata' => $responseData,
));
}
}

View File

@ -0,0 +1,35 @@
<?php
namespace Pheanstalk\Command;
use Pheanstalk\YamlResponseParser;
/**
* The 'stats' command.
* Statistical information about the system as a whole.
*
* @author Paul Annesley
* @package Pheanstalk
* @license http://www.opensource.org/licenses/mit-license.php
*/
class StatsCommand
extends AbstractCommand
{
/* (non-phpdoc)
* @see Command::getCommandLine()
*/
public function getCommandLine()
{
return 'stats';
}
/* (non-phpdoc)
* @see Command::getResponseParser()
*/
public function getResponseParser()
{
return new YamlResponseParser(
YamlResponseParser::MODE_DICT
);
}
}

View File

@ -0,0 +1,45 @@
<?php
namespace Pheanstalk\Command;
use Pheanstalk\YamlResponseParser;
/**
* The 'stats-job' command.
* Gives statistical information about the specified job if it exists.
*
* @author Paul Annesley
* @package Pheanstalk
* @license http://www.opensource.org/licenses/mit-license.php
*/
class StatsJobCommand
extends AbstractCommand
{
private $_jobId;
/**
* @param Job|int $job
*/
public function __construct($job)
{
$this->_jobId = is_object($job) ? $job->getId() : $job;
}
/* (non-phpdoc)
* @see Command::getCommandLine()
*/
public function getCommandLine()
{
return sprintf('stats-job %u', $this->_jobId);
}
/* (non-phpdoc)
* @see Command::getResponseParser()
*/