Merge pull request #303 from serroba/BIG-28720

Allowing to use a factory instead of manually instantiate the Jobs
This commit is contained in:
Chris Boulton 2016-10-14 14:56:45 -07:00 committed by GitHub
commit ee9f133bf9
7 changed files with 198 additions and 62 deletions

View File

@ -24,10 +24,15 @@ class Resque_Job
public $payload; public $payload;
/** /**
* @var object Instance of the class performing work for this job. * @var object|Resque_JobInterface Instance of the class performing work for this job.
*/ */
private $instance; private $instance;
/**
* @var Resque_Job_FactoryInterface
*/
private $jobFactory;
/** /**
* Instantiate a new instance of a job. * Instantiate a new instance of a job.
* *
@ -50,6 +55,7 @@ class Resque_Job
* @param string $id Unique identifier for tracking the job. Generated if not supplied. * @param string $id Unique identifier for tracking the job. Generated if not supplied.
* *
* @return string * @return string
* @throws \InvalidArgumentException
*/ */
public static function create($queue, $class, $args = null, $monitor = false, $id = null) public static function create($queue, $class, $args = null, $monitor = false, $id = null)
{ {
@ -76,41 +82,41 @@ class Resque_Job
return $id; return $id;
} }
/** /**
* Find the next available job from the specified queue and return an * Find the next available job from the specified queue and return an
* instance of Resque_Job for it. * instance of Resque_Job for it.
* *
* @param string $queue The name of the queue to check for a job in. * @param string $queue The name of the queue to check for a job in.
* @return null|object Null when there aren't any waiting jobs, instance of Resque_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) public static function reserve($queue)
{ {
$payload = Resque::pop($queue); $payload = Resque::pop($queue);
if(!is_array($payload)) { if(!is_array($payload)) {
return false; return false;
} }
return new Resque_Job($queue, $payload); return new Resque_Job($queue, $payload);
} }
/** /**
* Find the next available job from the specified queues using blocking list pop * Find the next available job from the specified queues using blocking list pop
* and return an instance of Resque_Job for it. * and return an instance of Resque_Job for it.
* *
* @param array $queues * @param array $queues
* @param int $timeout * @param int $timeout
* @return null|object Null when there aren't any waiting jobs, instance of Resque_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) public static function reserveBlocking(array $queues, $timeout = null)
{ {
$item = Resque::blpop($queues, $timeout); $item = Resque::blpop($queues, $timeout);
if(!is_array($item)) { if(!is_array($item)) {
return false; return false;
} }
return new Resque_Job($item['queue'], $item['payload']); return new Resque_Job($item['queue'], $item['payload']);
} }
/** /**
* Update the status of the current job. * Update the status of the current job.
@ -154,8 +160,8 @@ class Resque_Job
/** /**
* Get the instantiated object for this job that will be performing work. * Get the instantiated object for this job that will be performing work.
* * @return Resque_JobInterface Instance of the object that this job belongs to.
* @return object Instance of the object that this job belongs to. * @throws Resque_Exception
*/ */
public function getInstance() public function getInstance()
{ {
@ -163,23 +169,9 @@ class Resque_Job
return $this->instance; return $this->instance;
} }
if(!class_exists($this->payload['class'])) { $this->instance = $this->getJobFactory()->create($this->payload['class'], $this->getArguments(), $this->queue);
throw new Resque_Exception( $this->instance->job = $this;
'Could not find job class ' . $this->payload['class'] . '.' return $this->instance;
);
}
if(!method_exists($this->payload['class'], 'perform')) {
throw new Resque_Exception(
'Job class ' . $this->payload['class'] . ' does not contain a perform method.'
);
}
$this->instance = new $this->payload['class'];
$this->instance->job = $this;
$this->instance->args = $this->getArguments();
$this->instance->queue = $this->queue;
return $this->instance;
} }
/** /**
@ -272,4 +264,26 @@ class Resque_Job
} }
return '(' . implode(' | ', $name) . ')'; return '(' . implode(' | ', $name) . ')';
} }
/**
* @param Resque_Job_FactoryInterface $jobFactory
* @return Resque_Job
*/
public function setJobFactory(Resque_Job_FactoryInterface $jobFactory)
{
$this->jobFactory = $jobFactory;
return $this;
}
/**
* @return Resque_Job_FactoryInterface
*/
public function getJobFactory()
{
if ($this->jobFactory === null) {
$this->jobFactory = new Resque_Job_Factory();
}
return $this->jobFactory;
}
} }

View File

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

View File

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

View File

@ -0,0 +1,9 @@
<?php
interface Resque_JobInterface
{
/**
* @return bool
*/
public function perform();
}

View File

@ -31,7 +31,7 @@ class Resque_Tests_EventTest extends Resque_Tests_TestCase
$payload = array( $payload = array(
'class' => 'Test_Job', 'class' => 'Test_Job',
'args' => array( 'args' => array(
'somevar', array('somevar'),
), ),
); );
$job = new Resque_Job('jobs', $payload); $job = new Resque_Job('jobs', $payload);

View File

@ -183,16 +183,16 @@ class Resque_Tests_JobTest extends Resque_Tests_TestCase
public function testJobWithNamespace() public function testJobWithNamespace()
{ {
Resque_Redis::prefix('php'); Resque_Redis::prefix('php');
$queue = 'jobs'; $queue = 'jobs';
$payload = array('another_value'); $payload = array('another_value');
Resque::enqueue($queue, 'Test_Job_With_TearDown', $payload); Resque::enqueue($queue, 'Test_Job_With_TearDown', $payload);
$this->assertEquals(Resque::queues(), array('jobs')); $this->assertEquals(Resque::queues(), array('jobs'));
$this->assertEquals(Resque::size($queue), 1); $this->assertEquals(Resque::size($queue), 1);
Resque_Redis::prefix('resque'); Resque_Redis::prefix('resque');
$this->assertEquals(Resque::size($queue), 0); $this->assertEquals(Resque::size($queue), 0);
} }
public function testDequeueAll() public function testDequeueAll()
@ -362,4 +362,68 @@ class Resque_Tests_JobTest extends Resque_Tests_TestCase
$this->assertEquals(Resque::size($queue), 2); $this->assertEquals(Resque::size($queue), 2);
} }
public function testUseDefaultFactoryToGetJobInstance()
{
$payload = array(
'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 = array(
'class' => 'Some_Job_Class',
'args' => array(array())
);
$job = new Resque_Job('jobs', $payload);
$factory = new Some_Stub_Factory();
$job->setJobFactory($factory);
$instance = $job->getInstance();
$this->assertInstanceOf('Resque_JobInterface', $instance);
}
public function testDoNotUseFactoryToGetInstance()
{
$payload = array(
'class' => 'Some_Job_Class',
'args' => array(array())
);
$job = new Resque_Job('jobs', $payload);
$factory = $this->getMock('Resque_Job_FactoryInterface');
$testJob = $this->getMock('Resque_JobInterface');
$factory->expects(self::never())->method('create')->will(self::returnValue($testJob));
$instance = $job->getInstance();
$this->assertInstanceOf('Resque_JobInterface', $instance);
}
}
class Some_Job_Class implements Resque_JobInterface
{
/**
* @return bool
*/
public function perform()
{
return true;
}
}
class Some_Stub_Factory implements Resque_Job_FactoryInterface
{
/**
* @param $className
* @param array $args
* @param $queue
* @return Resque_JobInterface
*/
public function create($className, $args, $queue)
{
return new Some_Job_Class();
}
} }

View File

@ -11,6 +11,11 @@ class Resque_Tests_TestCase extends PHPUnit_Framework_TestCase
protected $resque; protected $resque;
protected $redis; protected $redis;
public static function setUpBeforeClass()
{
date_default_timezone_set('UTC');
}
public function setUp() public function setUp()
{ {
$config = file_get_contents(REDIS_CONF); $config = file_get_contents(REDIS_CONF);