Skip to content

Commit 7dd1474

Browse files
committed
Merge branch 'develop'
2 parents fdca42b + 25ff307 commit 7dd1474

File tree

16 files changed

+468
-117
lines changed

16 files changed

+468
-117
lines changed

.travis.yml

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,21 @@
11
language: php
22
php:
3-
- 5.6
4-
- 7.0
5-
- 7.1
3+
- '7.4'
4+
- '7.3'
5+
- '7.2'
6+
- '7.1'
7+
- '7.0'
8+
- '5.6'
69
- hhvm
710
matrix:
811
exclude:
912
- php: hhvm
1013
env: ENABLE_REDIS_EXT=1
14+
allow_failures:
15+
- php: '7.4'
16+
- php: '7.3'
17+
- php: '7.2'
18+
- php: hhvm
1119
env:
1220
- ENABLE_REDIS_EXT=0
1321
- ENABLE_REDIS_EXT=1

HOWITWORKS.md

Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -106,51 +106,54 @@ How do the workers process the queues?
106106
8. `Resque_Job->fail()` returns control to the worker (still in
107107
`Resque_Worker::work()`) without a value
108108
- Job
109-
1. The job calls `Resque_Worker->perform()` with the `Resque_Job` as
109+
1. `Resque_Job_PID` is created, registering the PID of the actual process
110+
doing the job.
111+
2. The job calls `Resque_Worker->perform()` with the `Resque_Job` as
110112
its only argument.
111-
2. `Resque_Worker->perform()` sets up a `try...catch` block so it can
113+
3. `Resque_Worker->perform()` sets up a `try...catch` block so it can
112114
properly handle exceptions by marking jobs as failed (by calling
113115
`Resque_Job->fail()`, as above)
114-
3. Inside the `try...catch`, `Resque_Worker->perform()` triggers an
116+
4. Inside the `try...catch`, `Resque_Worker->perform()` triggers an
115117
`afterFork` event
116-
4. Still inside the `try...catch`, `Resque_Worker->perform()` calls
118+
5. Still inside the `try...catch`, `Resque_Worker->perform()` calls
117119
`Resque_Job->perform()` with no arguments
118-
5. `Resque_Job->perform()` calls `Resque_Job->getInstance()` with no
120+
6. `Resque_Job->perform()` calls `Resque_Job->getInstance()` with no
119121
arguments
120-
6. If `Resque_Job->getInstance()` has already been called, it returns
122+
7. If `Resque_Job->getInstance()` has already been called, it returns
121123
the existing instance; otherwise:
122-
7. `Resque_Job->getInstance()` checks that the job's class (type)
124+
8. `Resque_Job->getInstance()` checks that the job's class (type)
123125
exists and has a `perform()` method; if not, in either case, it
124126
throws an exception which will be caught by
125127
`Resque_Worker->perform()`
126-
8. `Resque_Job->getInstance()` creates an instance of the job's class,
128+
9. `Resque_Job->getInstance()` creates an instance of the job's class,
127129
and initializes it with a reference to the `Resque_Job` itself, the
128130
job's arguments (which it gets by calling
129131
`Resque_Job->getArguments()`, which in turn simply returns the value
130132
of `args[0]`, or an empty array if no arguments were passed), and
131133
the queue name
132-
9. `Resque_Job->getInstance()` returns control, along with the job
134+
10. `Resque_Job->getInstance()` returns control, along with the job
133135
class instance, to `Resque_Job->perform()`
134-
10. `Resque_Job->perform()` sets up its own `try...catch` block to
136+
11. `Resque_Job->perform()` sets up its own `try...catch` block to
135137
handle `Resque_Job_DontPerform` exceptions; any other exceptions are
136138
passed up to `Resque_Worker->perform()`
137-
11. `Resque_Job->perform()` triggers a `beforePerform` event
138-
12. `Resque_Job->perform()` calls `setUp()` on the instance, if it
139+
12. `Resque_Job->perform()` triggers a `beforePerform` event
140+
13. `Resque_Job->perform()` calls `setUp()` on the instance, if it
139141
exists
140-
13. `Resque_Job->perform()` calls `perform()` on the instance
141-
14. `Resque_Job->perform()` calls `tearDown()` on the instance, if it
142+
14. `Resque_Job->perform()` calls `perform()` on the instance
143+
15. `Resque_Job->perform()` calls `tearDown()` on the instance, if it
142144
exists
143-
15. `Resque_Job->perform()` triggers an `afterPerform` event
144-
16. The `try...catch` block ends, suppressing `Resque_Job_DontPerform`
145+
16. `Resque_Job->perform()` triggers an `afterPerform` event
146+
17. The `try...catch` block ends, suppressing `Resque_Job_DontPerform`
145147
exceptions by returning control, and the value `FALSE`, to
146148
`Resque_Worker->perform()`; any other situation returns the value
147149
`TRUE` along with control, instead
148-
17. The `try...catch` block in `Resque_Worker->perform()` ends
149-
18. `Resque_Worker->perform()` updates the job status from `RUNNING` to
150+
18. The `try...catch` block in `Resque_Worker->perform()` ends
151+
19. `Resque_Worker->perform()` updates the job status from `RUNNING` to
150152
`COMPLETE`, then returns control, with no value, to the worker
151153
(again still in `Resque_Worker::work()`)
152-
19. `Resque_Worker::work()` calls `exit(0)` to terminate the job process
154+
20. `Resque_Job_PID()` is removed, the forked process will terminate soon
153155
cleanly
156+
21. `Resque_Worker::work()` calls `exit(0)` to terminate the job process
154157
- SPECIAL CASE: Non-forking OS (Windows)
155158
1. Same as the job above, except it doesn't call `exit(0)` when done
156159
7. `Resque_Worker::work()` calls `Resque_Worker->doneWorking()` with no

README.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,19 @@ Statuses are available for up to 24 hours after a job has completed or failed,
205205
and are then automatically expired. A status can also forcefully be expired by
206206
calling the `stop()` method on a status class.
207207

208+
### Obtaining job PID ###
209+
210+
You can obtain the PID of the actual process doing the work through `Resque_Job_PID`. On a forking OS this will be the
211+
PID of the forked process.
212+
213+
CAUTION: on a non-forking OS, the PID returned will be of the worker itself.
214+
215+
```php
216+
echo Resque_Job_PID::get($token);
217+
```
218+
219+
Function returns `0` if the `perform` hasn't started yet, or if it has already ended.
220+
208221
## Workers
209222

210223
Workers work in the exact same way as the Ruby workers. For complete
@@ -300,6 +313,15 @@ custom prefix to separate the Resque data:
300313
$ PREFIX=my-app-name bin/resque
301314
```
302315

316+
### Setting Redis backend ###
317+
318+
When you have the Redis database on a different host than the one the workers
319+
are running, you must set the `REDIS_BACKEND` environment variable:
320+
321+
```sh
322+
$ REDIS_BACKEND=my-redis-ip:my-redis-port bin/resque
323+
```
324+
303325
### Forking
304326

305327
Similarly to the Ruby versions, supported platforms will immediately fork after

composer.json

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,6 @@
2727
"role": "Creator"
2828
}
2929
],
30-
"repositories": [
31-
{
32-
"type": "vcs",
33-
"url": "https://github.com/chrisboulton/credis"
34-
}
35-
],
3630
"require": {
3731
"php": ">=5.3.0",
3832
"ext-pcntl": "*",
@@ -53,5 +47,10 @@
5347
"psr-0": {
5448
"Resque": "lib"
5549
}
56-
}
50+
},
51+
"extra": {
52+
"branch-alias": {
53+
"dev-master": "1.0-dev"
54+
}
55+
}
5756
}

demo/resque.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,4 @@
44
require 'job.php';
55
require 'php_error_job.php';
66

7-
require '../bin/resque';
7+
require __DIR__ . '/../bin/resque';

lib/Resque.php

Lines changed: 49 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,11 @@ class Resque
2828
*/
2929
protected static $redisDatabase = 0;
3030

31+
/**
32+
* @var string auth of Redis database
33+
*/
34+
protected static $auth;
35+
3136
/**
3237
* Given a host/port combination separated by a colon, set it as
3338
* the redis server that Resque will talk to.
@@ -37,11 +42,13 @@ class Resque
3742
* and returns a Resque_Redis instance, or
3843
* a nested array of servers with host/port pairs.
3944
* @param int $database
45+
* @param string $auth
4046
*/
41-
public static function setBackend($server, $database = 0)
47+
public static function setBackend($server, $database = 0, $auth = null)
4248
{
4349
self::$redisServer = $server;
4450
self::$redisDatabase = $database;
51+
self::$auth = $auth;
4552
self::$redis = null;
4653
}
4754

@@ -62,6 +69,10 @@ public static function redis()
6269
self::$redis = new Resque_Redis(self::$redisServer, self::$redisDatabase);
6370
}
6471

72+
if (!empty(self::$auth)) {
73+
self::$redis->auth(self::$auth);
74+
}
75+
6576
return self::$redis;
6677
}
6778

@@ -141,9 +152,9 @@ public static function pop($queue)
141152
public static function dequeue($queue, $items = Array())
142153
{
143154
if(count($items) > 0) {
144-
return self::removeItems($queue, $items);
155+
return self::removeItems($queue, $items);
145156
} else {
146-
return self::removeList($queue);
157+
return self::removeList($queue);
147158
}
148159
}
149160

@@ -213,10 +224,11 @@ public static function size($queue)
213224
* @param string $class The name of the class that contains the code to execute the job.
214225
* @param array $args Any optional arguments that should be passed when the job is executed.
215226
* @param boolean $trackStatus Set to true to be able to monitor the status of a job.
227+
* @param string $prefix The prefix needs to be set for the status key
216228
*
217229
* @return string|boolean Job ID when the job was created, false if creation was cancelled due to beforeEnqueue
218230
*/
219-
public static function enqueue($queue, $class, $args = null, $trackStatus = false)
231+
public static function enqueue($queue, $class, $args = null, $trackStatus = false, $prefix = "")
220232
{
221233
$id = Resque::generateJobId();
222234
$hookParams = array(
@@ -232,7 +244,7 @@ public static function enqueue($queue, $class, $args = null, $trackStatus = fals
232244
return false;
233245
}
234246

235-
Resque_Job::create($queue, $class, $args, $trackStatus, $id);
247+
Resque_Job::create($queue, $class, $args, $trackStatus, $id, $prefix);
236248
Resque_Event::trigger('afterEnqueue', $hookParams);
237249

238250
return $id;
@@ -263,6 +275,20 @@ public static function queues()
263275
return $queues;
264276
}
265277

278+
/**
279+
* Retrieve all the items of a queue with Redis
280+
*
281+
* @return array Array of items.
282+
*/
283+
public static function items($queue, $start = 0, $stop = -1)
284+
{
285+
$list = self::redis()->lrange('queue:' . $queue, $start, $stop);
286+
if(!is_array($list)) {
287+
$list = array();
288+
}
289+
return $list;
290+
}
291+
266292
/**
267293
* Remove Items from the queue
268294
* Safely moving each item to a temporary queue before processing it
@@ -317,7 +343,7 @@ private static function removeItems($queue, $items = Array())
317343

318344
/**
319345
* matching item
320-
* item can be ['class'] or ['class' => 'id'] or ['class' => {:foo => 1, :bar => 2}]
346+
* item can be ['class'] or ['class' => 'id'] or ['class' => {'foo' => 1, 'bar' => 2}]
321347
* @private
322348
*
323349
* @params string $string redis result in json
@@ -330,24 +356,24 @@ private static function matchItem($string, $items)
330356
$decoded = json_decode($string, true);
331357

332358
foreach($items as $key => $val) {
333-
# class name only ex: item[0] = ['class']
334-
if (is_numeric($key)) {
335-
if($decoded['class'] == $val) {
336-
return true;
337-
}
338-
# class name with args , example: item[0] = ['class' => {'foo' => 1, 'bar' => 2}]
339-
} elseif (is_array($val)) {
340-
$decodedArgs = (array)$decoded['args'][0];
341-
if ($decoded['class'] == $key &&
342-
count($decodedArgs) > 0 && count(array_diff($decodedArgs, $val)) == 0) {
343-
return true;
359+
# class name only ex: item[0] = ['class']
360+
if (is_numeric($key)) {
361+
if($decoded['class'] == $val) {
362+
return true;
363+
}
364+
# class name with args , example: item[0] = ['class' => {'foo' => 1, 'bar' => 2}]
365+
} elseif (is_array($val)) {
366+
$decodedArgs = (array)$decoded['args'][0];
367+
if ($decoded['class'] == $key &&
368+
count($decodedArgs) > 0 && count(array_diff($decodedArgs, $val)) == 0) {
369+
return true;
370+
}
371+
# class name with ID, example: item[0] = ['class' => 'id']
372+
} else {
373+
if ($decoded['class'] == $key && $decoded['id'] == $val) {
374+
return true;
375+
}
344376
}
345-
# class name with ID, example: item[0] = ['class' => 'id']
346-
} else {
347-
if ($decoded['class'] == $key && $decoded['id'] == $val) {
348-
return true;
349-
}
350-
}
351377
}
352378
return false;
353379
}

lib/Resque/Failure.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,20 @@ public static function create($payload, Exception $exception, Resque_Worker $wor
2828
new $backend($payload, $exception, $worker, $queue);
2929
}
3030

31+
/**
32+
* Create a new failed job on the backend from PHP 7 errors.
33+
*
34+
* @param object $payload The contents of the job that has just failed.
35+
* @param \Error $exception The PHP 7 error generated when the job failed to run.
36+
* @param \Resque_Worker $worker Instance of Resque_Worker that was running this job when it failed.
37+
* @param string $queue The name of the queue that this job was fetched from.
38+
*/
39+
public static function createFromError($payload, Error $exception, Resque_Worker $worker, $queue)
40+
{
41+
$backend = self::getBackend();
42+
new $backend($payload, $exception, $worker, $queue);
43+
}
44+
3145
/**
3246
* Return an instance of the backend for saving job failures.
3347
*

lib/Resque/Failure/Redis.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ class Resque_Failure_Redis implements Resque_Failure_Interface
2020
public function __construct($payload, $exception, $worker, $queue)
2121
{
2222
$data = new stdClass;
23-
$data->failed_at = strftime('%a %b %d %H:%M:%S %Z %Y');
23+
$data->failed_at = date('c');
2424
$data->payload = $payload;
2525
$data->exception = get_class($exception);
2626
$data->error = $exception->getMessage();

0 commit comments

Comments
 (0)