Skip to content

Commit a8322cd

Browse files
committed
Merge pull request #212 from chrisboulton/beforeEnqueue
Add beforeEnqueue hook
2 parents 1d24d00 + 0c39e2c commit a8322cd

File tree

6 files changed

+110
-30
lines changed

6 files changed

+110
-30
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ Changes by iskandar introduce improved support for using DSNs to connect to Redi
3333
* Fix an issue where a lost connection to Redis could cause an infinite loop (atorres757)
3434
* Add a helper method to `Resque_Redis` to remove the namespace applied to Redis keys (tonypiper)
3535
* Call beforePerform hook before retrieivng an instance of the job class (allows beforePerform to cancel a job with DontPerform before initialising your application)
36+
* Add `beforeEnqueue` hook, called before a job is placed on a queue
3637

3738
## 1.2 (2012-10-13) ##
3839

README.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -413,6 +413,18 @@ Called whenever a job fails. Arguments passed (in this order) include:
413413
* Exception - The exception that was thrown when the job failed
414414
* Resque_Job - The job that failed
415415

416+
#### beforeEnqueue ####
417+
418+
Called immediately before a job is enqueued using the `Resque::enqueue` method.
419+
Arguments passed (in this order) include:
420+
421+
* Class - string containing the name of the job to be enqueued
422+
* Arguments - array of arguments for the job
423+
* Queue - string containing the name of the queue the job is to be enqueued in
424+
* ID - string containing the token of the job to be enqueued
425+
426+
You can prevent enqueing of the job by throwing an exception of `Resque_Job_DontCreate`.
427+
416428
#### afterEnqueue ####
417429

418430
Called after a job has been queued using the `Resque::enqueue` method. Arguments passed

lib/Resque.php

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -197,21 +197,28 @@ public static function size($queue)
197197
* @param array $args Any optional arguments that should be passed when the job is executed.
198198
* @param boolean $trackStatus Set to true to be able to monitor the status of a job.
199199
*
200-
* @return string
200+
* @return string|boolean Job ID when the job was created, false if creation was cancelled due to beforeEnqueue
201201
*/
202202
public static function enqueue($queue, $class, $args = null, $trackStatus = false)
203203
{
204-
$result = Resque_Job::create($queue, $class, $args, $trackStatus);
205-
if ($result) {
206-
Resque_Event::trigger('afterEnqueue', array(
207-
'class' => $class,
208-
'args' => $args,
209-
'queue' => $queue,
210-
'id' => $result,
211-
));
204+
$id = Resque::generateJobId();
205+
$hookParams = array(
206+
'class' => $class,
207+
'args' => $args,
208+
'queue' => $queue,
209+
'id' => $id,
210+
);
211+
try {
212+
Resque_Event::trigger('beforeEnqueue', $hookParams);
213+
}
214+
catch(Resque_Job_DontCreate $e) {
215+
return false;
212216
}
213217

214-
return $result;
218+
Resque_Job::create($queue, $class, $args, $trackStatus, $id);
219+
Resque_Event::trigger('afterEnqueue', $hookParams);
220+
221+
return $id;
215222
}
216223

217224
/**
@@ -342,5 +349,15 @@ private static function removeList($queue)
342349
$result = self::redis()->del('queue:' . $queue);
343350
return ($result == 1) ? $counter : 0;
344351
}
352+
353+
/*
354+
* Generate an identifier to attach to a job for status tracking.
355+
*
356+
* @return string
357+
*/
358+
public static function generateJobId()
359+
{
360+
return md5(uniqid('', true));
361+
}
345362
}
346363

lib/Resque/Job.php

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,17 +47,21 @@ public function __construct($queue, $payload)
4747
* @param string $class The name of the class that contains the code to execute the job.
4848
* @param array $args Any optional arguments that should be passed when the job is executed.
4949
* @param boolean $monitor Set to true to be able to monitor the status of a job.
50+
* @param string $id Unique identifier for tracking the job. Generated if not supplied.
5051
*
5152
* @return string
5253
*/
53-
public static function create($queue, $class, $args = null, $monitor = false)
54+
public static function create($queue, $class, $args = null, $monitor = false, $id = null)
5455
{
56+
if (is_null($id)) {
57+
$id = Resque::generateJobId();
58+
}
59+
5560
if($args !== null && !is_array($args)) {
5661
throw new InvalidArgumentException(
5762
'Supplied $args must be an array.'
5863
);
5964
}
60-
$id = md5(uniqid('', true));
6165
Resque::push($queue, array(
6266
'class' => $class,
6367
'args' => array($args),

lib/Resque/Job/DontCreate.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?php
2+
/**
3+
* Exception to be thrown if while enqueuing a job it should not be created.
4+
*
5+
* @package Resque/Job
6+
* @author Chris Boulton <[email protected]>
7+
* @license http://www.opensource.org/licenses/mit-license.php
8+
*/
9+
class Resque_Job_DontCreate extends Exception
10+
{
11+
12+
}

test/Resque/Tests/EventTest.php

Lines changed: 52 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,11 @@
99
class Resque_Tests_EventTest extends Resque_Tests_TestCase
1010
{
1111
private $callbacksHit = array();
12-
12+
1313
public function setUp()
1414
{
1515
Test_Job::$called = false;
16-
16+
1717
// Register a worker to test with
1818
$this->worker = new Resque_Worker('jobs');
1919
$this->worker->setLogger(new Resque_Log());
@@ -38,7 +38,7 @@ public function getEventTestJob()
3838
$job->worker = $this->worker;
3939
return $job;
4040
}
41-
41+
4242
public function eventCallbackProvider()
4343
{
4444
return array(
@@ -47,7 +47,7 @@ public function eventCallbackProvider()
4747
array('afterFork', 'afterForkEventCallback'),
4848
);
4949
}
50-
50+
5151
/**
5252
* @dataProvider eventCallbackProvider
5353
*/
@@ -58,10 +58,10 @@ public function testEventCallbacksFire($event, $callback)
5858
$job = $this->getEventTestJob();
5959
$this->worker->perform($job);
6060
$this->worker->work(0);
61-
61+
6262
$this->assertContains($callback, $this->callbacksHit, $event . ' callback (' . $callback .') was not called');
6363
}
64-
64+
6565
public function testBeforeForkEventCallbackFires()
6666
{
6767
$event = 'beforeFork';
@@ -76,6 +76,18 @@ public function testBeforeForkEventCallbackFires()
7676
$this->assertContains($callback, $this->callbacksHit, $event . ' callback (' . $callback .') was not called');
7777
}
7878

79+
public function testBeforeEnqueueEventCallbackFires()
80+
{
81+
$event = 'beforeEnqueue';
82+
$callback = 'beforeEnqueueEventCallback';
83+
84+
Resque_Event::listen($event, array($this, $callback));
85+
Resque::enqueue('jobs', 'Test_Job', array(
86+
'somevar'
87+
));
88+
$this->assertContains($callback, $this->callbacksHit, $event . ' callback (' . $callback .') was not called');
89+
}
90+
7991
public function testBeforePerformEventCanStopWork()
8092
{
8193
$callback = 'beforePerformEventDontPerformCallback';
@@ -87,23 +99,35 @@ public function testBeforePerformEventCanStopWork()
8799
$this->assertContains($callback, $this->callbacksHit, $callback . ' callback was not called');
88100
$this->assertFalse(Test_Job::$called, 'Job was still performed though Resque_Job_DontPerform was thrown');
89101
}
90-
102+
103+
public function testBeforeEnqueueEventStopsJobCreation()
104+
{
105+
$callback = 'beforeEnqueueEventDontCreateCallback';
106+
Resque_Event::listen('beforeEnqueue', array($this, $callback));
107+
Resque_Event::listen('afterEnqueue', array($this, 'afterEnqueueEventCallback'));
108+
109+
$result = Resque::enqueue('test_job', 'TestClass');
110+
$this->assertContains($callback, $this->callbacksHit, $callback . ' callback was not called');
111+
$this->assertNotContains('afterEnqueueEventCallback', $this->callbacksHit, 'afterEnqueue was still called, even though it should not have been');
112+
$this->assertFalse($result);
113+
}
114+
91115
public function testAfterEnqueueEventCallbackFires()
92116
{
93117
$callback = 'afterEnqueueEventCallback';
94-
$event = 'afterEnqueue';
95-
118+
$event = 'afterEnqueue';
119+
96120
Resque_Event::listen($event, array($this, $callback));
97121
Resque::enqueue('jobs', 'Test_Job', array(
98122
'somevar'
99-
));
123+
));
100124
$this->assertContains($callback, $this->callbacksHit, $event . ' callback (' . $callback .') was not called');
101125
}
102126

103127
public function testStopListeningRemovesListener()
104128
{
105129
$callback = 'beforePerformEventCallback';
106-
$event = 'beforePerform';
130+
$event = 'beforePerform';
107131

108132
Resque_Event::listen($event, array($this, $callback));
109133
Resque_Event::stopListening($event, array($this, $callback));
@@ -112,18 +136,23 @@ public function testStopListeningRemovesListener()
112136
$this->worker->perform($job);
113137
$this->worker->work(0);
114138

115-
$this->assertNotContains($callback, $this->callbacksHit,
139+
$this->assertNotContains($callback, $this->callbacksHit,
116140
$event . ' callback (' . $callback .') was called though Resque_Event::stopListening was called'
117141
);
118142
}
119143

120-
121144
public function beforePerformEventDontPerformCallback($instance)
122145
{
123146
$this->callbacksHit[] = __FUNCTION__;
124147
throw new Resque_Job_DontPerform;
125148
}
126-
149+
150+
public function beforeEnqueueEventDontCreateCallback($queue, $class, $args, $track = false)
151+
{
152+
$this->callbacksHit[] = __FUNCTION__;
153+
throw new Resque_Job_DontCreate;
154+
}
155+
127156
public function assertValidEventCallback($function, $job)
128157
{
129158
$this->callbacksHit[] = $function;
@@ -133,7 +162,7 @@ public function assertValidEventCallback($function, $job)
133162
$args = $job->getArguments();
134163
$this->assertEquals($args[0], 'somevar');
135164
}
136-
165+
137166
public function afterEnqueueEventCallback($class, $args)
138167
{
139168
$this->callbacksHit[] = __FUNCTION__;
@@ -142,12 +171,17 @@ public function afterEnqueueEventCallback($class, $args)
142171
'somevar',
143172
), $args);
144173
}
145-
174+
175+
public function beforeEnqueueEventCallback($job)
176+
{
177+
$this->callbacksHit[] = __FUNCTION__;
178+
}
179+
146180
public function beforePerformEventCallback($job)
147181
{
148182
$this->assertValidEventCallback(__FUNCTION__, $job);
149183
}
150-
184+
151185
public function afterPerformEventCallback($job)
152186
{
153187
$this->assertValidEventCallback(__FUNCTION__, $job);
@@ -157,7 +191,7 @@ public function beforeForkEventCallback($job)
157191
{
158192
$this->assertValidEventCallback(__FUNCTION__, $job);
159193
}
160-
194+
161195
public function afterForkEventCallback($job)
162196
{
163197
$this->assertValidEventCallback(__FUNCTION__, $job);

0 commit comments

Comments
 (0)