Resque_Job   A
last analyzed

Complexity

Total Complexity 35

Size/Duplication

Total Lines 309
Duplicated Lines 0 %

Test Coverage

Coverage 92.16%

Importance

Changes 16
Bugs 1 Features 1
Metric Value
eloc 99
c 16
b 1
f 1
dl 0
loc 309
ccs 94
cts 102
cp 0.9216
rs 9.6
wmc 35

15 Methods

Rating   Name   Duplication   Size   Complexity  
A getJobFactory() 0 6 2
A __construct() 0 4 1
A reserveBlocking() 0 9 2
A getArguments() 0 7 2
A getStatus() 0 8 2
A reserve() 0 8 2
A getPrefix() 0 7 2
A getInstance() 0 9 2
A setJobFactory() 0 5 1
A perform() 0 25 4
A __toString() 0 13 3
A updateStatus() 0 8 2
A recreate() 0 11 3
A create() 0 24 5
A fail() 0 25 2
1
<?php
2
3
/**
4
 * Resque job.
5
 *
6
 * @package		Resque/Job
7
 * @author		Chris Boulton <[email protected]>
8
 * @license		http://www.opensource.org/licenses/mit-license.php
9
 */
10
class Resque_Job
11
{
12
	/**
13
	 * @var string The name of the queue that this job belongs to.
14
	 */
15
	public $queue;
16
17
	/**
18
	 * @var Resque_Worker Instance of the Resque worker running this job.
19
	 */
20
	public $worker;
21
22
	/**
23
	 * @var array Array containing details of the job.
24
	 */
25
	public $payload;
26
27
	/**
28
	 * @var object|Resque_JobInterface Instance of the class performing work for this job.
29
	 */
30
	private $instance;
31
32
	/**
33
	 * @var Resque_Job_FactoryInterface
34
	 */
35
	private $jobFactory;
36
37
	/**
38
	 * Instantiate a new instance of a job.
39
	 *
40
	 * @param string $queue The queue that the job belongs to.
41
	 * @param array $payload array containing details of the job.
42 35
	 */
43
	public function __construct($queue, $payload)
44 35
	{
45 35
		$this->queue = $queue;
46 35
		$this->payload = $payload;
47
	}
48
49
	/**
50
	 * Create a new job and save it to the specified queue.
51
	 *
52
	 * @param string $queue The name of the queue to place the job in.
53
	 * @param string $class The name of the class that contains the code to execute the job.
54
	 * @param array $args Any optional arguments that should be passed when the job is executed.
55
	 * @param boolean $monitor Set to true to be able to monitor the status of a job.
56
	 * @param string $id Unique identifier for tracking the job. Generated if not supplied.
57
	 * @param string $prefix The prefix needs to be set for the status key
58
	 *
59
	 * @return string
60
	 * @throws \InvalidArgumentException
61 47
	 */
62
	public static function create($queue, $class, $args = null, $monitor = false, $id = null, $prefix = "")
63 47
	{
64
		if (is_null($id)) {
65
			$id = Resque::generateJobId();
66
		}
67 47
68 1
		if ($args !== null && !is_array($args)) {
0 ignored issues
show
introduced by
The condition is_array($args) is always true.
Loading history...
69 1
			throw new InvalidArgumentException(
70
				'Supplied $args must be an array.'
71
			);
72 46
		}
73 46
		Resque::push($queue, array(
74 46
			'class'	     => $class,
75 46
			'args'	     => array($args),
76 46
			'id'	     => $id,
77 46
			'prefix'     => $prefix,
78
			'queue_time' => microtime(true),
79
		));
80 45
81 10
		if ($monitor) {
82
			Resque_Job_Status::create($id, $prefix);
83
		}
84 45
85
		return $id;
86
	}
87
88
	/**
89
	 * Find the next available job from the specified queue and return an
90
	 * instance of Resque_Job for it.
91
	 *
92
	 * @param string $queue The name of the queue to check for a job in.
93
	 * @return false|object Null when there aren't any waiting jobs, instance of Resque_Job when a job was found.
94 26
	 */
95
	public static function reserve($queue)
96 26
	{
97 26
		$payload = Resque::pop($queue);
98 17
		if (!is_array($payload)) {
0 ignored issues
show
introduced by
The condition is_array($payload) is always true.
Loading history...
99
			return false;
100
		}
101 22
102
		return new Resque_Job($queue, $payload);
103
	}
104
105
	/**
106
	 * Find the next available job from the specified queues using blocking list pop
107
	 * and return an instance of Resque_Job for it.
108
	 *
109
	 * @param array             $queues
110
	 * @param int               $timeout
111
	 * @return false|object Null when there aren't any waiting jobs, instance of Resque_Job when a job was found.
112 1
	 */
113
	public static function reserveBlocking(array $queues, $timeout = null)
114 1
	{
115
		$item = Resque::blpop($queues, $timeout);
116 1
117
		if (!is_array($item)) {
118
			return false;
119
		}
120 1
121
		return new Resque_Job($item['queue'], $item['payload']);
122
	}
123
124
	/**
125
	 * Update the status of the current job.
126
	 *
127
	 * @param int $status Status constant from Resque_Job_Status indicating the current status of a job.
128 18
	 */
129
	public function updateStatus($status, $result = null)
130 18
	{
131 7
		if (empty($this->payload['id'])) {
132
			return;
133
		}
134 12
135 12
		$statusInstance = new Resque_Job_Status($this->payload['id'], $this->getPrefix());
136 12
		$statusInstance->update($status, $result);
137
	}
138
139
	/**
140
	 * Return the status of the current job.
141
	 *
142
	 * @return int|null The status of the job as one of the Resque_Job_Status constants or null if job is not being tracked.
143 11
	 */
144
	public function getStatus()
145 11
	{
146 11
		if (empty($this->payload['id'])) {
147
			return null;
148
		}
149
150
		$status = new Resque_Job_Status($this->payload['id'], $this->getPrefix());
151
		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...
152
	}
153
154 16
	/**
155
	 * Get the arguments supplied to this job.
156 16
	 *
157 2
	 * @return array Array of arguments.
158
	 */
159
	public function getArguments()
160 14
	{
161
		if (!isset($this->payload['args'])) {
162
			return array();
163
		}
164
165
		return $this->payload['args'][0];
166
	}
167
168 12
	/**
169
	 * Get the instantiated object for this job that will be performing work.
170 12
	 * @return Resque_JobInterface Instance of the object that this job belongs to.
171
	 * @throws Resque_Exception
172
	 */
173
	public function getInstance()
174 12
	{
175 10
		if (!is_null($this->instance)) {
176 10
			return $this->instance;
177
		}
178
179
		$this->instance = $this->getJobFactory()->create($this->payload['class'], $this->getArguments(), $this->queue);
180
		$this->instance->job = $this;
0 ignored issues
show
Bug introduced by
Accessing job on the interface Resque_JobInterface suggest that you code against a concrete implementation. How about adding an instanceof check?
Loading history...
181
		return $this->instance;
182
	}
183
184
	/**
185
	 * Actually execute a job by calling the perform method on the class
186 10
	 * associated with the job with the supplied arguments.
187
	 *
188 10
	 * @return bool
189
	 * @throws Resque_Exception When the job's class could not be found or it does not contain a perform method.
190 10
	 */
191
	public function perform()
192 9
	{
193 7
		$result = true;
194 1
		try {
195
			Resque_Event::trigger('beforePerform', $this);
196
197 7
			$instance = $this->getInstance();
198
			if (is_callable([$instance, 'setUp'])) {
199 6
				$instance->setUp();
0 ignored issues
show
Bug introduced by
The method setUp() does not exist on Resque_JobInterface. ( Ignorable by Annotation )

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

199
				$instance->/** @scrutinizer ignore-call */ 
200
               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...
200 1
			}
201
202
			$result = $instance->perform();
203 6
204
			if (is_callable([$instance, 'tearDown'])) {
205
				$instance->tearDown();
0 ignored issues
show
Bug introduced by
The method tearDown() does not exist on Resque_JobInterface. ( Ignorable by Annotation )

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

205
				$instance->/** @scrutinizer ignore-call */ 
206
               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...
206 4
			}
207 1
208
			Resque_Event::trigger('afterPerform', $this);
209
		}
210 7
		// beforePerform/setUp have said don't perform this job. Return.
211
		catch (Resque_Job_DontPerform $e) {
212
			$result = false;
213
		}
214
215
		return $result;
216
	}
217
218 2
	/**
219
	 * Mark the current job as having failed.
220 2
	 *
221 2
	 * @param $exception
222 2
	 */
223
	public function fail($exception)
224
	{
225 2
		Resque_Event::trigger('onFailure', array(
226 2
			'exception' => $exception,
227
			'job' => $this,
228
		));
229
230
		$this->updateStatus(Resque_Job_Status::STATUS_FAILED);
231
		if ($exception instanceof Error) {
232
			Resque_Failure::createFromError(
233
				$this->payload,
234 2
				$exception,
235 2
				$this->worker,
236 2
				$this->queue
237 2
			);
238 2
		} else {
239
			Resque_Failure::create(
240
				$this->payload,
241 2
				$exception,
242 2
				$this->worker,
243 2
				$this->queue
244
			);
245
		}
246
		Resque_Stat::incr('failed');
247
		Resque_Stat::incr('failed:' . $this->worker);
248
	}
249 2
250
	/**
251 2
	 * Re-queue the current job.
252 2
	 * @return string
253 2
	 */
254 1
	public function recreate()
255
	{
256
		$monitor = false;
257 2
		if (!empty($this->payload['id'])) {
258
			$status = new Resque_Job_Status($this->payload['id'], $this->getPrefix());
259
			if ($status->isTracking()) {
260
				$monitor = true;
261
			}
262
		}
263
264
		return self::create($this->queue, $this->payload['class'], $this->getArguments(), $monitor, null, $this->getPrefix());
265 13
	}
266
267
	/**
268 13
	 * Generate a string representation used to describe the current job.
269
	 *
270 13
	 * @return string The string representation of the job.
271 9
	 */
272
	public function __toString()
273 13
	{
274 13
		$name = array(
275 12
			'Job{' . $this->queue . '}'
276
		);
277 13
		if (!empty($this->payload['id'])) {
278
			$name[] = 'ID: ' . $this->payload['id'];
279
		}
280
		$name[] = $this->payload['class'];
281
		if (!empty($this->payload['args'])) {
282
			$name[] = json_encode($this->payload['args']);
283
		}
284 1
		return '(' . implode(' | ', $name) . ')';
285
	}
286 1
287
	/**
288 1
	 * @param Resque_Job_FactoryInterface $jobFactory
289
	 * @return Resque_Job
290
	 */
291
	public function setJobFactory(Resque_Job_FactoryInterface $jobFactory)
292
	{
293
		$this->jobFactory = $jobFactory;
294 12
295
		return $this;
296 12
	}
297 11
298
	/**
299 12
	 * @return Resque_Job_FactoryInterface
300
	 */
301
	public function getJobFactory()
302 1
	{
303
		if ($this->jobFactory === null) {
304
			$this->jobFactory = new Resque_Job_Factory();
305
		}
306
		return $this->jobFactory;
307
	}
308
309
	/**
310
	 * @return string
311
	 */
312
	private function getPrefix()
313
	{
314
		if (isset($this->payload['prefix'])) {
315
			return $this->payload['prefix'];
316
		}
317
318
		return '';
319
	}
320
}
321