Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
72.58% covered (warning)
72.58%
45 / 62
57.14% covered (warning)
57.14%
8 / 14
CRAP
0.00% covered (danger)
0.00%
0 / 1
JobQueueMemory
73.77% covered (warning)
73.77%
45 / 61
57.14% covered (warning)
57.14%
8 / 14
42.15
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 doBatchPush
57.14% covered (warning)
57.14%
4 / 7
0.00% covered (danger)
0.00%
0 / 1
5.26
 supportedOrders
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 optimalOrder
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 doIsEmpty
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 doGetSize
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
2
 doGetAcquiredCount
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
6
 doPop
84.62% covered (warning)
84.62%
11 / 13
0.00% covered (danger)
0.00%
0 / 1
3.03
 doAck
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
6
 doDelete
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
12
 getAllQueuedJobs
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
2
 getAllAcquiredJobs
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
2
 jobFromSpecInternal
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getQueueData
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
3
1<?php
2/**
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write to the Free Software Foundation, Inc.,
15 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 * http://www.gnu.org/copyleft/gpl.html
17 *
18 * @file
19 */
20
21namespace MediaWiki\JobQueue;
22
23use ArrayIterator;
24use MappedIterator;
25use Wikimedia\ObjectCache\HashBagOStuff;
26use Wikimedia\ObjectCache\WANObjectCache;
27
28/**
29 * PHP memory-backed job queue storage, for testing.
30 *
31 * JobQueueGroup does not remember every queue instance, so statically track it here.
32 *
33 * @since 1.27
34 * @ingroup JobQueue
35 */
36class JobQueueMemory extends JobQueue {
37    /** @var array[] */
38    protected static $data = [];
39
40    public function __construct( array $params ) {
41        $params['wanCache'] = new WANObjectCache( [ 'cache' => new HashBagOStuff() ] );
42
43        parent::__construct( $params );
44    }
45
46    /**
47     * @see JobQueue::doBatchPush
48     *
49     * @param IJobSpecification[] $jobs
50     * @param int $flags
51     */
52    protected function doBatchPush( array $jobs, $flags ) {
53        $unclaimed =& $this->getQueueData( 'unclaimed', [] );
54
55        foreach ( $jobs as $job ) {
56            if ( $job->ignoreDuplicates() ) {
57                $sha1 = sha1( serialize( $job->getDeduplicationInfo() ) );
58                if ( !isset( $unclaimed[$sha1] ) ) {
59                    $unclaimed[$sha1] = $job;
60                }
61            } else {
62                $unclaimed[] = $job;
63            }
64        }
65    }
66
67    /**
68     * @see JobQueue::supportedOrders
69     *
70     * @return string[]
71     */
72    protected function supportedOrders() {
73        return [ 'random', 'timestamp', 'fifo' ];
74    }
75
76    /**
77     * @see JobQueue::optimalOrder
78     *
79     * @return string
80     */
81    protected function optimalOrder() {
82        return 'fifo';
83    }
84
85    /**
86     * @see JobQueue::doIsEmpty
87     *
88     * @return bool
89     */
90    protected function doIsEmpty() {
91        return ( $this->doGetSize() == 0 );
92    }
93
94    /**
95     * @see JobQueue::doGetSize
96     *
97     * @return int
98     */
99    protected function doGetSize() {
100        $unclaimed = $this->getQueueData( 'unclaimed' );
101
102        return $unclaimed ? count( $unclaimed ) : 0;
103    }
104
105    /**
106     * @see JobQueue::doGetAcquiredCount
107     *
108     * @return int
109     */
110    protected function doGetAcquiredCount() {
111        $claimed = $this->getQueueData( 'claimed' );
112
113        return $claimed ? count( $claimed ) : 0;
114    }
115
116    /**
117     * @see JobQueue::doPop
118     *
119     * @return RunnableJob|false
120     */
121    protected function doPop() {
122        if ( $this->doGetSize() == 0 ) {
123            return false;
124        }
125
126        $unclaimed =& $this->getQueueData( 'unclaimed' );
127        $claimed =& $this->getQueueData( 'claimed', [] );
128
129        if ( $this->order === 'random' ) {
130            $key = array_rand( $unclaimed );
131        } else {
132            $key = array_key_first( $unclaimed );
133        }
134
135        $spec = $unclaimed[$key];
136        unset( $unclaimed[$key] );
137        $claimed[] = $spec;
138
139        $job = $this->jobFromSpecInternal( $spec );
140
141        $job->setMetadata( 'claimId', array_key_last( $claimed ) );
142
143        return $job;
144    }
145
146    /**
147     * @see JobQueue::doAck
148     *
149     * @param RunnableJob $job
150     */
151    protected function doAck( RunnableJob $job ) {
152        if ( $this->getAcquiredCount() == 0 ) {
153            return;
154        }
155
156        $claimed =& $this->getQueueData( 'claimed' );
157        unset( $claimed[$job->getMetadata( 'claimId' )] );
158    }
159
160    /**
161     * @inheritDoc
162     */
163    protected function doDelete() {
164        if ( isset( self::$data[$this->type][$this->domain] ) ) {
165            unset( self::$data[$this->type][$this->domain] );
166            if ( !self::$data[$this->type] ) {
167                unset( self::$data[$this->type] );
168            }
169        }
170    }
171
172    /**
173     * @see JobQueue::getAllQueuedJobs
174     *
175     * @return \Iterator<RunnableJob> of Job objects.
176     */
177    public function getAllQueuedJobs() {
178        $unclaimed = $this->getQueueData( 'unclaimed' );
179        if ( !$unclaimed ) {
180            return new ArrayIterator( [] );
181        }
182
183        return new MappedIterator(
184            $unclaimed,
185            function ( $value ) {
186                return $this->jobFromSpecInternal( $value );
187            }
188        );
189    }
190
191    /**
192     * @see JobQueue::getAllAcquiredJobs
193     *
194     * @return \Iterator<RunnableJob> of Job objects.
195     */
196    public function getAllAcquiredJobs() {
197        $claimed = $this->getQueueData( 'claimed' );
198        if ( !$claimed ) {
199            return new ArrayIterator( [] );
200        }
201
202        return new MappedIterator(
203            $claimed,
204            function ( $value ) {
205                return $this->jobFromSpecInternal( $value );
206            }
207        );
208    }
209
210    /**
211     * @param IJobSpecification $spec
212     * @return RunnableJob
213     */
214    public function jobFromSpecInternal( IJobSpecification $spec ) {
215        return $this->factoryJob( $spec->getType(), $spec->getParams() );
216    }
217
218    /**
219     * @param string $field
220     * @param mixed|null $init
221     *
222     * @return mixed
223     */
224    private function &getQueueData( $field, $init = null ) {
225        if ( !isset( self::$data[$this->type][$this->domain][$field] ) ) {
226            if ( $init !== null ) {
227                self::$data[$this->type][$this->domain][$field] = $init;
228            } else {
229                return $init;
230            }
231        }
232
233        return self::$data[$this->type][$this->domain][$field];
234    }
235}
236
237/** @deprecated class alias since 1.44 */
238class_alias( JobQueueMemory::class, 'JobQueueMemory' );