Passed
Push — master ( fdca42...7dd147 )
by Hennik
03:23 queued 10s
created

Resque_Job::recreate()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 2

Importance

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

194
				$instance->/** @scrutinizer ignore-call */ 
195
               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...
195
			}
196
197 7
			$result = $instance->perform();
198
199 6
			if(is_callable([$instance, 'tearDown'])) {
200 1
				$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

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