Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
49.21% |
31 / 63 |
|
33.33% |
4 / 12 |
CRAP | |
0.00% |
0 / 1 |
JobSpecification | |
49.21% |
31 / 63 |
|
33.33% |
4 / 12 |
99.48 | |
0.00% |
0 / 1 |
__construct | |
68.75% |
11 / 16 |
|
0.00% |
0 / 1 |
3.27 | |||
validateParams | |
80.00% |
4 / 5 |
|
0.00% |
0 / 1 |
5.20 | |||
getType | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getParams | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getReleaseTimestamp | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
6 | |||
ignoreDuplicates | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getDeduplicationInfo | |
100.00% |
13 / 13 |
|
100.00% |
1 / 1 |
4 | |||
getRootJobParams | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
2 | |||
hasRootJobParams | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
6 | |||
isRootJob | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
6 | |||
toSerializableArray | |
0.00% |
0 / 10 |
|
0.00% |
0 / 1 |
2 | |||
newFromArray | |
0.00% |
0 / 6 |
|
0.00% |
0 / 1 |
2 |
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 | use MediaWiki\Http\Telemetry; |
22 | use MediaWiki\Page\PageReference; |
23 | use MediaWiki\Page\PageReferenceValue; |
24 | |
25 | /** |
26 | * Job queue task description base code. |
27 | * |
28 | * Example usage: |
29 | * @code |
30 | * $job = new JobSpecification( |
31 | * 'null', |
32 | * [ 'lives' => 1, 'usleep' => 100, 'pi' => 3.141569 ], |
33 | * [ 'removeDuplicates' => 1 ] |
34 | * ); |
35 | * MediaWikiServices::getInstance()->getJobQueueGroup()->push( $job ) |
36 | * @endcode |
37 | * |
38 | * @newable |
39 | * @since 1.23 |
40 | * @ingroup JobQueue |
41 | */ |
42 | class JobSpecification implements IJobSpecification { |
43 | /** @var string */ |
44 | protected $type; |
45 | |
46 | /** @var array Array of job parameters or false if none */ |
47 | protected $params; |
48 | |
49 | /** @var PageReference */ |
50 | protected $page; |
51 | |
52 | /** @var array */ |
53 | protected $opts; |
54 | |
55 | /** |
56 | * @param string $type |
57 | * @param array $params Map of key/values |
58 | * @param array $opts Map of key/values |
59 | * 'removeDuplicates' key - whether to remove duplicate jobs |
60 | * 'removeDuplicatesIgnoreParams' key - array with parameters to ignore for deduplication |
61 | * @param PageReference|null $page |
62 | */ |
63 | public function __construct( |
64 | $type, array $params, array $opts = [], ?PageReference $page = null |
65 | ) { |
66 | $params += [ |
67 | 'requestId' => Telemetry::getInstance()->getRequestId(), |
68 | ]; |
69 | $this->validateParams( $params ); |
70 | $this->validateParams( $opts ); |
71 | |
72 | $this->type = $type; |
73 | if ( $page ) { |
74 | // Make sure JobQueue classes can pull the title from parameters alone |
75 | if ( $page->getDBkey() !== '' ) { |
76 | $params += [ |
77 | 'namespace' => $page->getNamespace(), |
78 | 'title' => $page->getDBkey() |
79 | ]; |
80 | } |
81 | } else { |
82 | // We aim to remove the page from job specification and all we need |
83 | // is namespace/dbkey, so use LOCAL no matter what. |
84 | $page = PageReferenceValue::localReference( NS_SPECIAL, 'Badtitle/' . __CLASS__ ); |
85 | } |
86 | $this->params = $params; |
87 | $this->page = $page; |
88 | $this->opts = $opts; |
89 | } |
90 | |
91 | /** |
92 | * @param array $params |
93 | */ |
94 | protected function validateParams( array $params ) { |
95 | foreach ( $params as $p => $v ) { |
96 | if ( is_array( $v ) ) { |
97 | $this->validateParams( $v ); |
98 | } elseif ( !is_scalar( $v ) && $v !== null ) { |
99 | throw new UnexpectedValueException( "Job parameter $p is not JSON serializable." ); |
100 | } |
101 | } |
102 | } |
103 | |
104 | public function getType() { |
105 | return $this->type; |
106 | } |
107 | |
108 | public function getParams() { |
109 | return $this->params; |
110 | } |
111 | |
112 | public function getReleaseTimestamp() { |
113 | return isset( $this->params['jobReleaseTimestamp'] ) |
114 | ? wfTimestampOrNull( TS_UNIX, $this->params['jobReleaseTimestamp'] ) |
115 | : null; |
116 | } |
117 | |
118 | public function ignoreDuplicates() { |
119 | return !empty( $this->opts['removeDuplicates'] ); |
120 | } |
121 | |
122 | public function getDeduplicationInfo() { |
123 | $info = [ |
124 | 'type' => $this->getType(), |
125 | 'params' => $this->getParams() |
126 | ]; |
127 | if ( is_array( $info['params'] ) ) { |
128 | // Identical jobs with different "root" jobs should count as duplicates |
129 | unset( $info['params']['rootJobSignature'] ); |
130 | unset( $info['params']['rootJobTimestamp'] ); |
131 | // Likewise for jobs with different delay times |
132 | unset( $info['params']['jobReleaseTimestamp'] ); |
133 | // Identical jobs from different requests should count as duplicates |
134 | unset( $info['params']['requestId'] ); |
135 | if ( isset( $this->opts['removeDuplicatesIgnoreParams'] ) ) { |
136 | foreach ( $this->opts['removeDuplicatesIgnoreParams'] as $field ) { |
137 | unset( $info['params'][$field] ); |
138 | } |
139 | } |
140 | } |
141 | |
142 | return $info; |
143 | } |
144 | |
145 | public function getRootJobParams() { |
146 | return [ |
147 | 'rootJobSignature' => $this->params['rootJobSignature'] ?? null, |
148 | 'rootJobTimestamp' => $this->params['rootJobTimestamp'] ?? null |
149 | ]; |
150 | } |
151 | |
152 | public function hasRootJobParams() { |
153 | return isset( $this->params['rootJobSignature'] ) |
154 | && isset( $this->params['rootJobTimestamp'] ); |
155 | } |
156 | |
157 | public function isRootJob() { |
158 | return $this->hasRootJobParams() && !empty( $this->params['rootJobIsSelf'] ); |
159 | } |
160 | |
161 | /** |
162 | * @deprecated since 1.41 |
163 | * @return array Field/value map that can immediately be serialized |
164 | * @since 1.25 |
165 | */ |
166 | public function toSerializableArray() { |
167 | wfDeprecated( __METHOD__, '1.41' ); |
168 | return [ |
169 | 'type' => $this->type, |
170 | 'params' => $this->params, |
171 | 'opts' => $this->opts, |
172 | 'title' => [ |
173 | 'ns' => $this->page->getNamespace(), |
174 | 'key' => $this->page->getDBkey() |
175 | ] |
176 | ]; |
177 | } |
178 | |
179 | /** |
180 | * @param array $map Field/value map |
181 | * @return JobSpecification |
182 | * @since 1.25 |
183 | */ |
184 | public static function newFromArray( array $map ) { |
185 | return new self( |
186 | $map['type'], |
187 | $map['params'], |
188 | $map['opts'], |
189 | PageReferenceValue::localReference( $map['title']['ns'], $map['title']['key'] ) |
190 | ); |
191 | } |
192 | } |