Test Failed
Pull Request — develop (#54)
by
unknown
02:26
created

JobHandler   A

Complexity

Total Complexity 35

Size/Duplication

Total Lines 317
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 105
dl 0
loc 317
rs 9.6
c 1
b 0
f 0
wmc 35

15 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A reserveBlocking() 0 9 2
A updateStatus() 0 8 2
A reserve() 0 8 2
A create() 0 24 5
A fail() 0 25 2
A getInstance() 0 9 2
A perform() 0 24 4
A __toString() 0 13 3
A recreate() 0 17 3
A setJobFactory() 0 5 1
A getStatus() 0 8 2
A getArguments() 0 7 2
A getPrefix() 0 7 2
A getJobFactory() 0 6 2
1
<?php
2
3
namespace Resque;
4
5
use InvalidArgumentException;
6
use Resque\Job\Status;
7
use Resque\Exceptions\DoNotPerformException;
8
use Resque\Job\FactoryInterface;
9
use Resque\Job\Factory;
10
use Error;
11
12
/**
13
 * Resque job.
14
 *
15
 * @package		Resque/JobHandler
16
 * @author		Chris Boulton <[email protected]>
17
 * @license		http://www.opensource.org/licenses/mit-license.php
18
 */
19
class JobHandler
20
{
21
	/**
22
	 * @var string The name of the queue that this job belongs to.
23
	 */
24
	public $queue;
25
26
	/**
27
	 * @var \Resque\Worker\Resque Instance of the Resque worker running this job.
28
	 */
29
	public $worker;
30
31
	/**
32
	 * @var array Array containing details of the job.
33
	 */
34
	public $payload;
35
36
	/**
37
	 * @var object|\Resque\Job\JobInterface Instance of the class performing work for this job.
38
	 */
39
	private $instance;
40
41
	/**
42
	 * @var \Resque\Job\FactoryInterface
43
	 */
44
	private $jobFactory;
45
46
	/**
47
	 * Instantiate a new instance of a job.
48
	 *
49
	 * @param string $queue The queue that the job belongs to.
50
	 * @param array $payload array containing details of the job.
51
	 */
52
	public function __construct($queue, $payload)
53
	{
54
		$this->queue = $queue;
55
		$this->payload = $payload;
56
	}
57
58
	/**
59
	 * Create a new job and save it to the specified queue.
60
	 *
61
	 * @param string $queue The name of the queue to place the job in.
62
	 * @param string $class The name of the class that contains the code to execute the job.
63
	 * @param array $args Any optional arguments that should be passed when the job is executed.
64
	 * @param boolean $monitor Set to true to be able to monitor the status of a job.
65
	 * @param string $id Unique identifier for tracking the job. Generated if not supplied.
66
	 * @param string $prefix The prefix needs to be set for the status key
67
	 *
68
	 * @return string
69
	 * @throws \InvalidArgumentException
70
	 */
71
	public static function create($queue, $class, $args = null, $monitor = false, $id = null, $prefix = "")
72
	{
73
		if (is_null($id)) {
74
			$id = Resque::generateJobId();
75
		}
76
77
		if ($args !== null && !is_array($args)) {
0 ignored issues
show
introduced by
The condition is_array($args) is always true.
Loading history...
78
			throw new InvalidArgumentException(
79
				'Supplied $args must be an array.'
80
			);
81
		}
82
		Resque::push($queue, array(
83
			'class'	     => $class,
84
			'args'	     => array($args),
85
			'id'	     => $id,
86
			'prefix'     => $prefix,
87
			'queue_time' => microtime(true),
88
		));
89
90
		if ($monitor) {
91
			Status::create($id, $prefix);
92
		}
93
94
		return $id;
95
	}
96
97
	/**
98
	 * Find the next available job from the specified queue and return an
99
	 * instance of JobHandler for it.
100
	 *
101
	 * @param string $queue The name of the queue to check for a job in.
102
	 * @return false|object Null when there aren't any waiting jobs, instance of Resque\JobHandler when a job was found.
103
	 */
104
	public static function reserve($queue)
105
	{
106
		$payload = Resque::pop($queue);
107
		if (!is_array($payload)) {
0 ignored issues
show
introduced by
The condition is_array($payload) is always true.
Loading history...
108
			return false;
109
		}
110
111
		return new JobHandler($queue, $payload);
112
	}
113
114
	/**
115
	 * Find the next available job from the specified queues using blocking list pop
116
	 * and return an instance of JobHandler for it.
117
	 *
118
	 * @param array             $queues
119
	 * @param int               $timeout
120
	 * @return false|object Null when there aren't any waiting jobs, instance of Resque\JobHandler when a job was found.
121
	 */
122
	public static function reserveBlocking(array $queues, $timeout = null)
123
	{
124
		$item = Resque::blpop($queues, $timeout);
125
126
		if (!is_array($item)) {
127
			return false;
128
		}
129
130
		return new JobHandler($item['queue'], $item['payload']);
131
	}
132
133
	/**
134
	 * Update the status of the current job.
135
	 *
136
	 * @param int $status Status constant from Resque\Job\Status indicating the current status of a job.
137
	 */
138
	public function updateStatus($status, $result = null)
139
	{
140
		if (empty($this->payload['id'])) {
141
			return;
142
		}
143
144
		$statusInstance = new Status($this->payload['id'], $this->getPrefix());
145
		$statusInstance->update($status, $result);
146
	}
147
148
	/**
149
	 * Return the status of the current job.
150
	 *
151
	 * @return int|null The status of the job as one of the Resque\Job\Status constants
152
	 *                  or null if job is not being tracked.
153
	 */
154
	public function getStatus()
155
	{
156
		if (empty($this->payload['id'])) {
157
			return null;
158
		}
159
160
		$status = new Status($this->payload['id'], $this->getPrefix());
161
		return $status->get();
0 ignored issues
show
Bug Best Practice introduced by
The expression return $status->get() could also return false which is incompatible with the documented return type integer|null. Did you maybe forget to handle an error condition?

If the returned type also contains false, it is an indicator that maybe an error condition leading to the specific return statement remains unhandled.

Loading history...
162
	}
163
164
	/**
165
	 * Get the arguments supplied to this job.
166
	 *
167
	 * @return array Array of arguments.
168
	 */
169
	public function getArguments()
170
	{
171
		if (!isset($this->payload['args'])) {
172
			return array();
173
		}
174
175
		return $this->payload['args'][0];
176
	}
177
178
	/**
179
	 * Get the instantiated object for this job that will be performing work.
180
	 * @return \Resque\Job\JobInterface Instance of the object that this job belongs to.
181
	 * @throws \Resque\Exceptions\ResqueException
182
	 */
183
	public function getInstance()
184
	{
185
		if (!is_null($this->instance)) {
186
			return $this->instance;
187
		}
188
189
		$this->instance = $this->getJobFactory()->create($this->payload['class'], $this->getArguments(), $this->queue);
190
		$this->instance->job = $this;
191
		return $this->instance;
192
	}
193
194
	/**
195
	 * Actually execute a job by calling the perform method on the class
196
	 * associated with the job with the supplied arguments.
197
	 *
198
	 * @return bool
199
	 * @throws Resque\Exceptions\ResqueException When the job's class could not be found
200
	 * 											 or it does not contain a perform method.
201
	 */
202
	public function perform()
203
	{
204
		$result = true;
205
		try {
206
			Event::trigger('beforePerform', $this);
207
208
			$instance = $this->getInstance();
209
			if (is_callable([$instance, 'setUp'])) {
210
				$instance->setUp();
0 ignored issues
show
Bug introduced by
The method setUp() does not exist on Resque\Job\JobInterface. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

210
				$instance->/** @scrutinizer ignore-call */ 
211
               setUp();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
211
			}
212
213
			$result = $instance->perform();
214
215
			if (is_callable([$instance, 'tearDown'])) {
216
				$instance->tearDown();
0 ignored issues
show
Bug introduced by
The method tearDown() does not exist on Resque\Job\JobInterface. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

216
				$instance->/** @scrutinizer ignore-call */ 
217
               tearDown();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
217
			}
218
219
			Event::trigger('afterPerform', $this);
220
		} catch (DoNotPerformException $e) {
221
			// beforePerform/setUp have said don't perform this job. Return.
222
			$result = false;
223
		}
224
225
		return $result;
226
	}
227
228
	/**
229
	 * Mark the current job as having failed.
230
	 *
231
	 * @param $exception
232
	 */
233
	public function fail($exception)
234
	{
235
		Event::trigger('onFailure', array(
236
			'exception' => $exception,
237
			'job' => $this,
238
		));
239
240
		$this->updateStatus(Status::STATUS_FAILED);
241
		if ($exception instanceof Error) {
242
			FailureHandler::createFromError(
243
				$this->payload,
244
				$exception,
245
				$this->worker,
246
				$this->queue
247
			);
248
		} else {
249
			FailureHandler::create(
250
				$this->payload,
251
				$exception,
252
				$this->worker,
253
				$this->queue
254
			);
255
		}
256
		Stat::incr('failed');
257
		Stat::incr('failed:' . $this->worker);
258
	}
259
260
	/**
261
	 * Re-queue the current job.
262
	 * @return string
263
	 */
264
	public function recreate()
265
	{
266
		$monitor = false;
267
		if (!empty($this->payload['id'])) {
268
			$status = new Status($this->payload['id'], $this->getPrefix());
269
			if ($status->isTracking()) {
270
				$monitor = true;
271
			}
272
		}
273
274
		return self::create(
275
			$this->queue,
276
			$this->payload['class'],
277
			$this->getArguments(),
278
			$monitor,
279
			null,
280
			$this->getPrefix()
281
		);
282
	}
283
284
	/**
285
	 * Generate a string representation used to describe the current job.
286
	 *
287
	 * @return string The string representation of the job.
288
	 */
289
	public function __toString()
290
	{
291
		$name = array(
292
			'Job{' . $this->queue . '}'
293
		);
294
		if (!empty($this->payload['id'])) {
295
			$name[] = 'ID: ' . $this->payload['id'];
296
		}
297
		$name[] = $this->payload['class'];
298
		if (!empty($this->payload['args'])) {
299
			$name[] = json_encode($this->payload['args']);
300
		}
301
		return '(' . implode(' | ', $name) . ')';
302
	}
303
304
	/**
305
	 * @param Resque\Job\FactoryInterface $jobFactory
0 ignored issues
show
Bug introduced by
The type Resque\Resque\Job\FactoryInterface was not found. Did you mean Resque\Job\FactoryInterface? If so, make sure to prefix the type with \.
Loading history...
306
	 * @return Resque\JobHandler
0 ignored issues
show
Bug introduced by
The type Resque\Resque\JobHandler was not found. Did you mean Resque\JobHandler? If so, make sure to prefix the type with \.
Loading history...
307
	 */
308
	public function setJobFactory(FactoryInterface $jobFactory)
309
	{
310
		$this->jobFactory = $jobFactory;
311
312
		return $this;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this returns the type Resque\JobHandler which is incompatible with the documented return type Resque\Resque\JobHandler.
Loading history...
313
	}
314
315
	/**
316
	 * @return Resque\Job\FactoryInterface
317
	 */
318
	public function getJobFactory()
319
	{
320
		if ($this->jobFactory === null) {
321
			$this->jobFactory = new Factory();
322
		}
323
		return $this->jobFactory;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->jobFactory returns the type Resque\Job\Factory|Resque\Job\FactoryInterface which is incompatible with the documented return type Resque\Resque\Job\FactoryInterface.
Loading history...
324
	}
325
326
	/**
327
	 * @return string
328
	 */
329
	private function getPrefix()
330
	{
331
		if (isset($this->payload['prefix'])) {
332
			return $this->payload['prefix'];
333
		}
334
335
		return '';
336
	}
337
}
338