14 function __construct( $name =
null, array $data = [], $dataName =
'' ) {
15 parent::__construct( $name, $data, $dataName );
17 $this->tablesUsed[] =
'job';
24 if ( $this->
getCliArg(
'use-jobqueue' ) ) {
25 $name = $this->
getCliArg(
'use-jobqueue' );
27 throw new MWException(
"No \$wgJobTypeConf entry for '$name'." );
31 $baseConfig = [
'class' => JobQueueDBSingle::class ];
33 $baseConfig[
'type'] =
'null';
36 'queueRand' => [
'order' =>
'random',
'claimTTL' => 0 ],
37 'queueRandTTL' => [
'order' =>
'random',
'claimTTL' => 10 ],
38 'queueTimestamp' => [
'order' =>
'timestamp',
'claimTTL' => 0 ],
39 'queueTimestampTTL' => [
'order' =>
'timestamp',
'claimTTL' => 10 ],
40 'queueFifo' => [
'order' =>
'fifo',
'claimTTL' => 0 ],
41 'queueFifoTTL' => [
'order' =>
'fifo',
'claimTTL' => 10 ],
43 foreach ( $variants as $q => $settings ) {
57 'queueRand',
'queueRandTTL',
'queueTimestamp',
'queueTimestampTTL',
58 'queueFifo',
'queueFifoTTL'
75 $this->markTestSkipped( $desc );
77 $this->assertEquals(
wfWikiID(),
$queue->getWiki(),
"Proper wiki ID ($desc)" );
87 $this->markTestSkipped( $desc );
89 $this->assertEquals(
'null',
$queue->getType(),
"Proper job type ($desc)" );
99 $this->markTestSkipped( $desc );
102 $this->assertTrue(
$queue->isEmpty(),
"Queue is empty ($desc)" );
105 $this->assertEquals( 0,
$queue->getSize(),
"Queue is empty ($desc)" );
106 $this->assertEquals( 0,
$queue->getAcquiredCount(),
"Queue is empty ($desc)" );
108 $this->assertNull(
$queue->push( $this->newJob() ),
"Push worked ($desc)" );
109 $this->assertNull(
$queue->batchPush( [ $this->newJob() ] ),
"Push worked ($desc)" );
111 $this->assertFalse(
$queue->isEmpty(),
"Queue is not empty ($desc)" );
114 $this->assertEquals( 2,
$queue->getSize(),
"Queue size is correct ($desc)" );
115 $this->assertEquals( 0,
$queue->getAcquiredCount(),
"No jobs active ($desc)" );
116 $jobs = iterator_to_array(
$queue->getAllQueuedJobs() );
117 $this->assertEquals( 2, count( $jobs ),
"Queue iterator size is correct ($desc)" );
120 $this->assertFalse(
$queue->isEmpty(),
"Queue is not empty ($desc)" );
123 $this->assertEquals( 1,
$queue->getSize(),
"Queue size is correct ($desc)" );
127 $this->assertEquals( 1,
$queue->getAcquiredCount(),
"Active job count ($desc)" );
131 $this->assertTrue(
$queue->isEmpty(),
"Queue is empty ($desc)" );
132 $this->assertEquals( 0,
$queue->getSize(),
"Queue is empty ($desc)" );
136 $this->assertEquals( 2,
$queue->getAcquiredCount(),
"Active job count ($desc)" );
143 $this->assertEquals( 1,
$queue->getAcquiredCount(),
"Active job count ($desc)" );
149 $this->assertEquals( 0,
$queue->getAcquiredCount(),
"Active job count ($desc)" );
151 $this->assertNull(
$queue->batchPush( [ $this->newJob(), $this->newJob() ] ),
152 "Push worked ($desc)" );
153 $this->assertFalse(
$queue->isEmpty(),
"Queue is not empty ($desc)" );
157 $this->assertTrue(
$queue->isEmpty(),
"Queue is empty ($desc)" );
158 $this->assertEquals( 0,
$queue->getSize(),
"Queue is empty ($desc)" );
168 $this->markTestSkipped( $desc );
171 $this->assertTrue(
$queue->isEmpty(),
"Queue is empty ($desc)" );
174 $this->assertEquals( 0,
$queue->getSize(),
"Queue is empty ($desc)" );
175 $this->assertEquals( 0,
$queue->getAcquiredCount(),
"Queue is empty ($desc)" );
179 [ $this->newDedupedJob(), $this->newDedupedJob(), $this->newDedupedJob() ]
181 "Push worked ($desc)" );
183 $this->assertFalse(
$queue->isEmpty(),
"Queue is not empty ($desc)" );
186 $this->assertEquals( 1,
$queue->getSize(),
"Queue size is correct ($desc)" );
187 $this->assertEquals( 0,
$queue->getAcquiredCount(),
"No jobs active ($desc)" );
191 [ $this->newDedupedJob(), $this->newDedupedJob(), $this->newDedupedJob() ]
193 "Push worked ($desc)"
196 $this->assertFalse(
$queue->isEmpty(),
"Queue is not empty ($desc)" );
199 $this->assertEquals( 1,
$queue->getSize(),
"Queue size is correct ($desc)" );
200 $this->assertEquals( 0,
$queue->getAcquiredCount(),
"No jobs active ($desc)" );
203 $this->assertTrue(
$queue->isEmpty(),
"Queue is empty ($desc)" );
206 $this->assertEquals( 0,
$queue->getSize(),
"Queue is empty ($desc)" );
208 $this->assertEquals( 1,
$queue->getAcquiredCount(),
"Active job count ($desc)" );
214 $this->assertEquals( 0,
$queue->getAcquiredCount(),
"Active job count ($desc)" );
224 $this->markTestSkipped( $desc );
247 $this->markTestSkipped( $desc );
250 $this->assertTrue(
$queue->isEmpty(),
"Queue is empty ($desc)" );
253 $this->assertEquals( 0,
$queue->getSize(),
"Queue is empty ($desc)" );
254 $this->assertEquals( 0,
$queue->getAcquiredCount(),
"Queue is empty ($desc)" );
258 for ( $i = 0; $i < 5; ++$i ) {
259 $this->assertNull(
$queue->push( $this->newJob( 0, $root1 ) ),
"Push worked ($desc)" );
261 $queue->deduplicateRootJob( $this->
newJob( 0, $root1 ) );
264 # Add a second to UNIX epoch and format back to TS_MW
265 $root2_ts = strtotime( $root2[
'rootJobTimestamp'] );
267 $root2[
'rootJobTimestamp'] =
wfTimestamp( TS_MW, $root2_ts );
269 $this->assertNotEquals( $root1[
'rootJobTimestamp'], $root2[
'rootJobTimestamp'],
270 "Root job signatures have different timestamps." );
271 for ( $i = 0; $i < 5; ++$i ) {
272 $this->assertNull(
$queue->push( $this->newJob( 0, $root2 ) ),
"Push worked ($desc)" );
274 $queue->deduplicateRootJob( $this->
newJob( 0, $root2 ) );
276 $this->assertFalse(
$queue->isEmpty(),
"Queue is not empty ($desc)" );
279 $this->assertEquals( 10,
$queue->getSize(),
"Queue size is correct ($desc)" );
280 $this->assertEquals( 0,
$queue->getAcquiredCount(),
"No jobs active ($desc)" );
295 $this->assertEquals( 10, count( $jobs ),
"Correct number of jobs popped ($desc)" );
296 $this->assertEquals( 5, $dupcount,
"Correct number of duplicate jobs popped ($desc)" );
306 $this->markTestSkipped( $desc );
309 $this->assertTrue(
$queue->isEmpty(),
"Queue is empty ($desc)" );
312 $this->assertEquals( 0,
$queue->getSize(),
"Queue is empty ($desc)" );
313 $this->assertEquals( 0,
$queue->getAcquiredCount(),
"Queue is empty ($desc)" );
315 for ( $i = 0; $i < 10; ++$i ) {
316 $this->assertNull(
$queue->push( $this->newJob( $i ) ),
"Push worked ($desc)" );
319 for ( $i = 0; $i < 10; ++$i ) {
321 $this->assertTrue(
$job instanceof
Job,
"Jobs popped from queue ($desc)" );
323 $this->assertEquals( $i,
$params[
'i'],
"Job popped from queue is FIFO ($desc)" );
327 $this->assertFalse(
$queue->pop(),
"Queue is not empty ($desc)" );
330 $this->assertEquals( 0,
$queue->getSize(),
"Queue is empty ($desc)" );
331 $this->assertEquals( 0,
$queue->getAcquiredCount(),
"No jobs active ($desc)" );
339 if ( !
$queue || !method_exists(
$queue,
'getServerQueuesWithJobs' ) ) {
340 $this->markTestSkipped();
343 $this->assertNotContains(
345 $queue->getServerQueuesWithJobs(),
346 "Null queue not in listing"
351 $this->assertContains(
353 $queue->getServerQueuesWithJobs(),
354 "Null queue in listing"
360 [
'queueRand',
false,
'Random queue without ack()' ],
361 [
'queueRandTTL',
true,
'Random queue with ack()' ],
362 [
'queueTimestamp',
false,
'Time ordered queue without ack()' ],
363 [
'queueTimestampTTL',
true,
'Time ordered queue with ack()' ],
364 [
'queueFifo',
false,
'FIFO ordered queue without ack()' ],
365 [
'queueFifoTTL',
true,
'FIFO ordered queue with ack()' ]
371 [
'queueFifo',
false,
'Ordered queue without ack()' ],
372 [
'queueFifoTTL',
true,
'Ordered queue with ack()' ]
376 function newJob( $i = 0, $rootJob = [] ) {
377 return new NullJob( Title::newMainPage(),
378 [
'lives' => 0,
'usleep' => 0,
'removeDuplicates' => 0,
'i' => $i ] + $rootJob );
382 return new NullJob( Title::newMainPage(),
383 [
'lives' => 0,
'usleep' => 0,
'removeDuplicates' => 1,
'i' => $i ] + $rootJob );
388 protected function getDB( $index ) {
389 $lb = MediaWikiServices::getInstance()->getDBLoadBalancer();
391 return $lb->getConnection( $index, [], $this->wiki );
$wgJobTypeConf
Map of job types to configuration arrays.
wfRandomString( $length=32)
Get a random string containing a number of pseudo-random hex characters.
wfTimestamp( $outputtype=TS_UNIX, $ts=0)
Get a timestamp string in one of various formats.
wfWikiID()
Get an ASCII string identifying this wiki This is used as a prefix in memcached keys.
No-op job that does nothing.
Class to handle job queues stored in the DB.
JobQueue medium Database.
testBasicOperations( $queue, $recycles, $desc)
provider_queueLists JobQueue
testJobOrder( $queue, $recycles, $desc)
provider_fifoQueueLists JobQueue
testRootDeduplication( $queue, $recycles, $desc)
provider_queueLists JobQueue
static provider_queueLists()
__construct( $name=null, array $data=[], $dataName='')
static provider_fifoQueueLists()
testBasicDeduplication( $queue, $recycles, $desc)
provider_queueLists JobQueue
testDeduplicationWhileClaimed( $queue, $recycles, $desc)
provider_queueLists JobQueue
newJob( $i=0, $rootJob=[])
testQueueAggregateTable()
JobQueue.
testGetWiki( $queue, $recycles, $desc)
provider_queueLists JobQueue::getWiki
testGetType( $queue, $recycles, $desc)
provider_queueLists JobQueue::getType
newDedupedJob( $i=0, $rootJob=[])
static factory(array $params)
Get a job queue object of the specified type.
Class to both describe a background job and handle jobs.
static newRootJobParams( $key)
Get "root job" parameters for a task.
Degenerate job that does nothing, but can optionally replace itself in the queue and/or sleep for a b...
Allows to change the fields on the form that will be generated $name
returning false will NOT prevent logging $e
if(count( $args)< 1) $job