diff --git a/README.md b/README.md index 3a1860d..a254bc0 100644 --- a/README.md +++ b/README.md @@ -139,8 +139,17 @@ class My_Job This method can be used to conveniently remove a job from a queue. ```php -// Removes 'My_Job' of queue 'default' +// Removes job class 'My_Job' of queue 'default' Resque::dequeue('default', ['My_Job']); + +// Removes job class 'My_Job' with Job ID '087df5819a790ac666c9608e2234b21e' of queue 'default' +Resuque::dequeue('default', ['My_Job' => '087df5819a790ac666c9608e2234b21e']); + +// 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', ['My_Job', 'My_Job2']); ``` If no jobs are given, this method will dequeue all jobs matching the provided queue. diff --git a/lib/Resque.php b/lib/Resque.php index c83b601..a26eaa6 100644 --- a/lib/Resque.php +++ b/lib/Resque.php @@ -257,8 +257,7 @@ class Resque $string = self::redis()->rpoplpush($originalQueue, self::redis()->getPrefix() . $tempQueue); if(!empty($string)) { - $decoded = json_decode($string, true); - if(in_array($decoded['class'], $items)) { + if(self::matchItem($string, $items)) { $counter++; } else { self::redis()->rpoplpush($tempQueue, self::redis()->getPrefix() . $requeueQueue); @@ -284,6 +283,43 @@ class Resque return $counter; } + /** + * matching item + * item can be ['class'] or ['class' => 'id'] or ['class' => {:foo => 1, :bar => 2}] + * @private + * + * @params string $string redis result in json + * @params $items + * + * @return (bool) + */ + private static function matchItem($string, $items) + { + $decoded = json_decode($string, true); + + foreach($items as $key => $val) { + # class name only ex: item[0] = ['class'] + if (is_numeric($key)) { + if($decoded['class'] == $val) { + return true; + } + # 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) { + return true; + } + # class name with ID, example: item[0] = ['class' => 'id'] + } else { + if ($decoded['class'] == $key && $decoded['id'] == $val) { + return true; + } + } + } + return false; + } + /** * Remove List * diff --git a/lib/Resque/Redis.php b/lib/Resque/Redis.php index 3d3848d..59ca215 100644 --- a/lib/Resque/Redis.php +++ b/lib/Resque/Redis.php @@ -77,7 +77,7 @@ class Resque_Redis 'zscore', 'zremrangebyscore', 'sort', - 'rename' + 'rename', 'rpoplpush' ); // sinterstore diff --git a/test/Resque/Tests/JobTest.php b/test/Resque/Tests/JobTest.php index f3a6e99..d0faa53 100644 --- a/test/Resque/Tests/JobTest.php +++ b/test/Resque/Tests/JobTest.php @@ -253,4 +253,76 @@ class Resque_Tests_JobTest extends Resque_Tests_TestCase $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 = array('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 = array('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'); + $qid = Resque::enqueue($queue, 'Test_Job_Dequeue'); + $this->assertEquals(Resque::size($queue), 2); + $test = array('Test_Job_Dequeue' => 'r4nD0mH4sh3dId'); + $this->assertEquals(Resque::dequeue($queue, $test), 0); + $this->assertEquals(Resque::size($queue), 2); + } + + public function testDequeueItemWithArg() + { + $queue = 'jobs'; + $arg = array('foo' => 1, 'bar' => 2); + Resque::enqueue($queue, 'Test_Job_Dequeue9'); + Resque::enqueue($queue, 'Test_Job_Dequeue9', $arg); + $this->assertEquals(Resque::size($queue), 2); + $test = array('Test_Job_Dequeue9' => $arg); + $this->assertEquals(Resque::dequeue($queue, $test), 1); + #$this->assertEquals(Resque::size($queue), 1); + } + + public function testDequeueItemWithUnorderedArg() + { + $queue = 'jobs'; + $arg = array('foo' => 1, 'bar' => 2); + $arg2 = array('bar' => 2, 'foo' => 1); + Resque::enqueue($queue, 'Test_Job_Dequeue'); + Resque::enqueue($queue, 'Test_Job_Dequeue', $arg); + $this->assertEquals(Resque::size($queue), 2); + $test = array('Test_Job_Dequeue' => $arg2); + $this->assertEquals(Resque::dequeue($queue, $test), 1); + $this->assertEquals(Resque::size($queue), 1); + } + + public function testDequeueItemWithiWrongArg() + { + $queue = 'jobs'; + $arg = array('foo' => 1, 'bar' => 2); + $arg2 = array('foo' => 2, 'bar' => 3); + Resque::enqueue($queue, 'Test_Job_Dequeue'); + Resque::enqueue($queue, 'Test_Job_Dequeue', $arg); + $this->assertEquals(Resque::size($queue), 2); + $test = array('Test_Job_Dequeue' => $arg2); + $this->assertEquals(Resque::dequeue($queue, $test), 0); + $this->assertEquals(Resque::size($queue), 2); + } + }