Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
73.77% covered (warning)
73.77%
45 / 61
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
21/**
22 * PHP memory-backed job queue storage, for testing.
23 *
24 * JobQueueGroup does not remember every queue instance, so statically track it here.
25 *
26 * @since 1.27
27 * @ingroup JobQueue
28 */
29class JobQueueMemory extends JobQueue {
30    /** @var array[] */
31    protected static $data = [];
32
33    public function __construct( array $params ) {
34        $params['wanCache'] = new WANObjectCache( [ 'cache' => new HashBagOStuff() ] );
35
36        parent::__construct( $params );
37    }
38
39    /**
40     * @see JobQueue::doBatchPush
41     *
42     * @param IJobSpecification[] $jobs
43     * @param int $flags
44     */
45    protected function doBatchPush( array $jobs, $flags ) {
46        $unclaimed =& $this->getQueueData( 'unclaimed', [] );
47
48        foreach ( $jobs as $job ) {
49            if ( $job->ignoreDuplicates() ) {
50                $sha1 = sha1( serialize( $job->getDeduplicationInfo() ) );
51                if ( !isset( $unclaimed[$sha1] ) ) {
52                    $unclaimed[$sha1] = $job;
53                }
54            } else {
55                $unclaimed[] = $job;
56            }
57        }
58    }
59
60    /**
61     * @see JobQueue::supportedOrders
62     *
63     * @return string[]
64     */
65    protected function supportedOrders() {
66        return [ 'random', 'timestamp', 'fifo' ];
67    }
68
69    /**
70     * @see JobQueue::optimalOrder
71     *
72     * @return string
73     */
74    protected function optimalOrder() {
75        return 'fifo';
76    }
77
78    /**
79     * @see JobQueue::doIsEmpty
80     *
81     * @return bool
82     */
83    protected function doIsEmpty() {
84        return ( $this->doGetSize() == 0 );
85    }
86
87    /**
88     * @see JobQueue::doGetSize
89     *
90     * @return int
91     */
92    protected function doGetSize() {
93        $unclaimed = $this->getQueueData( 'unclaimed' );
94
95        return $unclaimed ? count( $unclaimed ) : 0;
96    }
97
98    /**
99     * @see JobQueue::doGetAcquiredCount
100     *
101     * @return int
102     */
103    protected function doGetAcquiredCount() {
104        $claimed = $this->getQueueData( 'claimed' );
105
106        return $claimed ? count( $claimed ) : 0;
107    }
108
109    /**
110     * @see JobQueue::doPop
111     *
112     * @return RunnableJob|false
113     */
114    protected function doPop() {
115        if ( $this->doGetSize() == 0 ) {
116            return false;
117        }
118
119        $unclaimed =& $this->getQueueData( 'unclaimed' );
120        $claimed =& $this->getQueueData( 'claimed', [] );
121
122        if ( $this->order === 'random' ) {
123            $key = array_rand( $unclaimed );
124        } else {
125            $key = array_key_first( $unclaimed );
126        }
127
128        $spec = $unclaimed[$key];
129        unset( $unclaimed[$key] );
130        $claimed[] = $spec;
131
132        $job = $this->jobFromSpecInternal( $spec );
133
134        $job->setMetadata( 'claimId', array_key_last( $claimed ) );
135
136        return $job;
137    }
138
139    /**
140     * @see JobQueue::doAck
141     *
142     * @param RunnableJob $job
143     */
144    protected function doAck( RunnableJob $job ) {
145        if ( $this->getAcquiredCount() == 0 ) {
146            return;
147        }
148
149        $claimed =& $this->getQueueData( 'claimed' );
150        unset( $claimed[$job->getMetadata( 'claimId' )] );
151    }
152
153    /**
154     * @inheritDoc
155     */
156    protected function doDelete() {
157        if ( isset( self::$data[$this->type][$this->domain] ) ) {
158            unset( self::$data[$this->type][$this->domain] );
159            if ( !self::$data[$this->type] ) {
160                unset( self::$data[$this->type] );
161            }
162        }
163    }
164
165    /**
166     * @see JobQueue::getAllQueuedJobs
167     *
168     * @return Iterator<RunnableJob> of Job objects.
169     */
170    public function getAllQueuedJobs() {
171        $unclaimed = $this->getQueueData( 'unclaimed' );
172        if ( !$unclaimed ) {
173            return new ArrayIterator( [] );
174        }
175
176        return new MappedIterator(
177            $unclaimed,
178            function ( $value ) {
179                return $this->jobFromSpecInternal( $value );
180            }
181        );
182    }
183
184    /**
185     * @see JobQueue::getAllAcquiredJobs
186     *
187     * @return Iterator<RunnableJob> of Job objects.
188     */
189    public function getAllAcquiredJobs() {
190        $claimed = $this->getQueueData( 'claimed' );
191        if ( !$claimed ) {
192            return new ArrayIterator( [] );
193        }
194
195        return new MappedIterator(
196            $claimed,
197            function ( $value ) {
198                return $this->jobFromSpecInternal( $value );
199            }
200        );
201    }
202
203    /**
204     * @param IJobSpecification $spec
205     * @return RunnableJob
206     */
207    public function jobFromSpecInternal( IJobSpecification $spec ) {
208        return $this->factoryJob( $spec->getType(), $spec->getParams() );
209    }
210
211    /**
212     * @param string $field
213     * @param mixed|null $init
214     *
215     * @return mixed
216     */
217    private function &getQueueData( $field, $init = null ) {
218        if ( !isset( self::$data[$this->type][$this->domain][$field] ) ) {
219            if ( $init !== null ) {
220                self::$data[$this->type][$this->domain][$field] = $init;
221            } else {
222                return $init;
223            }
224        }
225
226        return self::$data[$this->type][$this->domain][$field];
227    }
228}