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