Skip to content

Commit d324639

Browse files
committed
Add RandomQueueOrderReserver.
This reserver simply shuffles the list of available queues (whether configured or retrieved dynamically from redis) on each call to reserve() meaning a random queue is used to reserve a job from.
1 parent dcbb8f2 commit d324639

File tree

2 files changed

+155
-0
lines changed

2 files changed

+155
-0
lines changed
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
namespace Resque\Reserver;
4+
5+
/**
6+
* RandomQueueOrderReserver randomises the list of queues before then reserving a job off the first available queue.
7+
*/
8+
class RandomQueueOrderReserver extends QueueOrderReserver implements ReserverInterface
9+
{
10+
/**
11+
* Gets the queues to reserve jobs from in random order.
12+
*
13+
* @return array
14+
*/
15+
public function getQueues()
16+
{
17+
$queues = parent::getQueues();
18+
shuffle($queues);
19+
return $queues;
20+
}
21+
}
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
<?php
2+
3+
namespace Resque\Tests\Reserver;
4+
5+
use Resque\Reserver\RandomQueueOrderReserver;
6+
use Resque;
7+
8+
class RandomQueueOrderReserverTest extends \Resque_Tests_TestCase
9+
{
10+
protected function getReserver(array $queues = array())
11+
{
12+
return new RandomQueueOrderReserver(new \Resque_Log(), $queues);
13+
}
14+
15+
public function testGetName()
16+
{
17+
$this->assertEquals('RandomQueueOrderReserver', $this->getReserver()->getName());
18+
}
19+
20+
public function testWaitAfterReservationAttemptReturnsTrue()
21+
{
22+
$this->assertTrue($this->getReserver()->waitAfterReservationAttempt());
23+
}
24+
25+
private function assertQueuesAreShuffled(RandomQueueOrderReserver $reserver, array $queues)
26+
{
27+
// retrieve the queues 20 times
28+
$shuffledQueues = array();
29+
for ($x = 0; $x < 20; $x++) {
30+
$shuffledQueues[] = $reserver->getQueues();
31+
}
32+
33+
$ordered = 0;
34+
foreach ($shuffledQueues as $shuffled) {
35+
// check if the order
36+
if ($shuffled === $queues) {
37+
$ordered++;
38+
}
39+
40+
// check that the shuffled queues contain all the right elements though
41+
sort($shuffled);
42+
$this->assertEquals($queues, $shuffled);
43+
}
44+
45+
// if all the shuffled queues were actually returned in sorted order then the shuffling is (unlikely) to be working
46+
$this->assertNotEquals(20, $ordered, "queues were ordered 20 times; queues not shuffled correctly");
47+
}
48+
49+
public function testGetQueuesReturnsConfiguredQueuesInShuffledOrder()
50+
{
51+
$queues = array(
52+
'queue_a',
53+
'queue_b',
54+
'queue_c',
55+
'queue_d',
56+
'queue_e',
57+
'queue_f',
58+
);
59+
60+
$reserver = $this->getReserver($queues);
61+
62+
$this->assertQueuesAreShuffled($reserver, $queues);
63+
}
64+
65+
public function testGetQueuesWithAsterixQueueReturnsAllQueuesFromRedisInShuffledOrder()
66+
{
67+
$queues = array(
68+
'queue_a',
69+
'queue_b',
70+
'queue_c',
71+
'queue_d',
72+
'queue_e',
73+
'queue_f',
74+
);
75+
76+
// register queues in redis
77+
foreach ($queues as $queue) {
78+
Resque::redis()->sadd('queues', $queue);
79+
}
80+
81+
$reserver = $this->getReserver(array('*'));
82+
83+
$this->assertQueuesAreShuffled($reserver, $queues);
84+
}
85+
86+
public function testReserverWhenNoJobsEnqueuedReturnsNull()
87+
{
88+
$queues = array(
89+
'queue_1',
90+
'queue_2',
91+
'queue_3',
92+
);
93+
$this->assertNull($this->getReserver($queues)->reserve());
94+
}
95+
96+
public function testReserveReservesJobsFromRandomQueue()
97+
{
98+
$queues = array(
99+
'queue_a',
100+
'queue_b',
101+
'queue_c',
102+
'queue_d',
103+
'queue_e',
104+
'queue_f',
105+
);
106+
107+
$reserver = $this->getReserver($queues);
108+
109+
$jobsPerQueue = 5;
110+
111+
// enqueue a bunch of jobs in each queue
112+
foreach ($queues as $queue) {
113+
for ($x = 0; $x < $jobsPerQueue; $x++) {
114+
$queuesForAllJobs[] = $queue;
115+
Resque::enqueue($queue, 'Test_Job');
116+
}
117+
}
118+
119+
$totalJobs = count($queues) * $jobsPerQueue;
120+
121+
// track the queue for each reserved job
122+
$reservedQueues = array();
123+
for ($x = 0; $x < $totalJobs; $x++) {
124+
$job = $reserver->reserve();
125+
$this->assertNotNull($job);
126+
$reservedQueues[] = $job->queue;
127+
}
128+
129+
// if jobs are reserved randomly, then $queueOrder shouldn't be ordered
130+
$orderedQueues = $reservedQueues;
131+
sort($orderedQueues);
132+
$this->assertNotEquals($orderedQueues, $reservedQueues, "queues were ordered; queues not shuffled correctly");
133+
}
134+
}

0 commit comments

Comments
 (0)