resque 1.23.0 → 2.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/HISTORY.md +271 -0
- data/README.markdown +454 -484
- data/Rakefile +4 -17
- data/bin/resque-web +10 -22
- data/lib/resque/data_store.rb +335 -0
- data/lib/resque/errors.rb +15 -1
- data/lib/resque/failure/airbrake.rb +32 -4
- data/lib/resque/failure/base.rb +16 -7
- data/lib/resque/failure/multiple.rb +26 -8
- data/lib/resque/failure/redis.rb +92 -15
- data/lib/resque/failure/redis_multi_queue.rb +104 -0
- data/lib/resque/failure.rb +62 -32
- data/lib/resque/helpers.rb +11 -57
- data/lib/resque/job.rb +79 -12
- data/lib/resque/log_formatters/quiet_formatter.rb +7 -0
- data/lib/resque/log_formatters/verbose_formatter.rb +7 -0
- data/lib/resque/log_formatters/very_verbose_formatter.rb +8 -0
- data/lib/resque/logging.rb +18 -0
- data/lib/resque/plugin.rb +22 -10
- data/lib/resque/railtie.rb +10 -0
- data/lib/resque/server/public/jquery-3.6.0.min.js +2 -0
- data/lib/resque/server/public/jquery.relatize_date.js +4 -4
- data/lib/resque/server/public/main.js +3 -0
- data/lib/resque/server/public/ranger.js +16 -8
- data/lib/resque/server/public/style.css +13 -8
- data/lib/resque/server/views/error.erb +1 -1
- data/lib/resque/server/views/failed.erb +27 -59
- data/lib/resque/server/views/failed_job.erb +50 -0
- data/lib/resque/server/views/failed_queues_overview.erb +24 -0
- data/lib/resque/server/views/job_class.erb +8 -0
- data/lib/resque/server/views/key_sets.erb +2 -4
- data/lib/resque/server/views/key_string.erb +1 -1
- data/lib/resque/server/views/layout.erb +7 -6
- data/lib/resque/server/views/next_more.erb +22 -10
- data/lib/resque/server/views/processing.erb +2 -0
- data/lib/resque/server/views/queues.erb +22 -13
- data/lib/resque/server/views/stats.erb +5 -5
- data/lib/resque/server/views/workers.erb +4 -4
- data/lib/resque/server/views/working.erb +10 -11
- data/lib/resque/server.rb +51 -108
- data/lib/resque/server_helper.rb +185 -0
- data/lib/resque/stat.rb +19 -7
- data/lib/resque/tasks.rb +26 -25
- data/lib/resque/thread_signal.rb +24 -0
- data/lib/resque/vendor/utf8_util.rb +2 -8
- data/lib/resque/version.rb +1 -1
- data/lib/resque/web_runner.rb +374 -0
- data/lib/resque/worker.rb +487 -163
- data/lib/resque.rb +332 -52
- data/lib/tasks/redis.rake +11 -11
- metadata +169 -149
- data/lib/resque/failure/hoptoad.rb +0 -33
- data/lib/resque/failure/thoughtbot.rb +0 -33
- data/lib/resque/server/public/jquery-1.3.2.min.js +0 -19
- data/lib/resque/server/test_helper.rb +0 -19
- data/lib/resque/vendor/utf8_util/utf8_util_18.rb +0 -91
- data/lib/resque/vendor/utf8_util/utf8_util_19.rb +0 -5
- data/test/airbrake_test.rb +0 -27
- data/test/hoptoad_test.rb +0 -26
- data/test/job_hooks_test.rb +0 -464
- data/test/job_plugins_test.rb +0 -230
- data/test/plugin_test.rb +0 -116
- data/test/redis-test-cluster.conf +0 -115
- data/test/redis-test.conf +0 -115
- data/test/resque-web_test.rb +0 -59
- data/test/resque_failure_redis_test.rb +0 -19
- data/test/resque_test.rb +0 -278
- data/test/test_helper.rb +0 -178
- data/test/worker_test.rb +0 -657
data/README.markdown
CHANGED
@@ -1,10 +1,18 @@
|
|
1
1
|
Resque
|
2
2
|
======
|
3
3
|
|
4
|
+
[![Gem Version](https://badge.fury.io/rb/resque.svg)](https://rubygems.org/gems/resque)
|
5
|
+
[![Build Status](https://github.com/resque/resque/actions/workflows/ci.yml/badge.svg)](https://github.com/resque/resque/actions/workflows/ci.yml)
|
6
|
+
|
7
|
+
Introduction
|
8
|
+
------------
|
9
|
+
|
4
10
|
Resque (pronounced like "rescue") is a Redis-backed library for creating
|
5
11
|
background jobs, placing those jobs on multiple queues, and processing
|
6
12
|
them later.
|
7
13
|
|
14
|
+
For the backstory, philosophy, and history of Resque's beginnings, please see [the blog post](http://github.com/blog/542-introducing-resque) (2009).
|
15
|
+
|
8
16
|
Background jobs can be any Ruby class or module that responds to
|
9
17
|
`perform`. Your existing classes can easily be converted to background
|
10
18
|
jobs or you can create new classes specifically to do work. Or, you
|
@@ -17,10 +25,11 @@ three parts:
|
|
17
25
|
2. A Rake task for starting a worker which processes jobs
|
18
26
|
3. A Sinatra app for monitoring queues, jobs, and workers.
|
19
27
|
|
20
|
-
Resque workers can be
|
21
|
-
|
22
|
-
|
23
|
-
|
28
|
+
Resque workers can be given multiple queues (a "queue list"),
|
29
|
+
distributed between multiple machines,
|
30
|
+
run anywhere with network access to the Redis server,
|
31
|
+
support priorities, are resilient to memory bloat / "leaks,"
|
32
|
+
tell you what they're doing, and expect failure.
|
24
33
|
|
25
34
|
Resque queues are persistent; support constant time, atomic push and
|
26
35
|
pop (thanks to Redis); provide visibility into their contents; and
|
@@ -30,19 +39,18 @@ The Resque frontend tells you what workers are doing, what workers are
|
|
30
39
|
not doing, what queues you're using, what's in those queues, provides
|
31
40
|
general usage stats, and helps you track failures.
|
32
41
|
|
42
|
+
Resque now supports Ruby 2.3.0 and above.
|
43
|
+
We will also only be supporting Redis 3.0 and above going forward.
|
33
44
|
|
34
|
-
|
35
|
-
-------------
|
36
|
-
|
37
|
-
For the backstory, philosophy, and history of Resque's beginnings,
|
38
|
-
please see [the blog post][0].
|
45
|
+
### Note on the future of Resque
|
39
46
|
|
47
|
+
Would you like to be involved in Resque? Do you have thoughts about what
|
48
|
+
Resque should be and do going forward? There's currently an [open discussion here](https://github.com/resque/resque/issues/1759)
|
49
|
+
on just that topic, so please feel free to join in. We'd love to hear your thoughts
|
50
|
+
and/or have people volunteer to be a part of the project!
|
40
51
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
Resque allows you to create jobs and place them on a queue, then,
|
45
|
-
later, pull those jobs off the queue and process them.
|
52
|
+
Example
|
53
|
+
-------
|
46
54
|
|
47
55
|
Resque jobs are Ruby classes (or modules) which respond to the
|
48
56
|
`perform` method. Here's an example:
|
@@ -102,105 +110,42 @@ This starts one Resque worker and tells it to work off the
|
|
102
110
|
find any more, at which point it will sleep for a small period and
|
103
111
|
repeatedly poll the queue for more jobs.
|
104
112
|
|
105
|
-
|
106
|
-
|
107
|
-
access to the Redis server.
|
108
|
-
|
109
|
-
|
110
|
-
Jobs
|
111
|
-
----
|
112
|
-
|
113
|
-
What should you run in the background? Anything that takes any time at
|
114
|
-
all. Slow INSERT statements, disk manipulating, data processing, etc.
|
115
|
-
|
116
|
-
At GitHub we use Resque to process the following types of jobs:
|
113
|
+
Installation
|
114
|
+
------------
|
117
115
|
|
118
|
-
|
119
|
-
* Counting disk usage
|
120
|
-
* Building tarballs
|
121
|
-
* Building Rubygems
|
122
|
-
* Firing off web hooks
|
123
|
-
* Creating events in the db and pre-caching them
|
124
|
-
* Building graphs
|
125
|
-
* Deleting users
|
126
|
-
* Updating our search index
|
116
|
+
Add the gem to your Gemfile:
|
127
117
|
|
128
|
-
|
118
|
+
gem 'resque'
|
129
119
|
|
130
|
-
|
131
|
-
mention "foreground" and "background" because they make conceptual
|
132
|
-
sense. You could easily be spidering sites and sticking data which
|
133
|
-
needs to be crunched later into a queue.
|
120
|
+
Next, install it with Bundler:
|
134
121
|
|
122
|
+
$ bundle
|
135
123
|
|
136
|
-
|
124
|
+
#### Rack
|
137
125
|
|
138
|
-
|
139
|
-
example from above. We'll run the following code to create a job:
|
126
|
+
In your Rakefile, or some other file in `lib/tasks` (ex: `lib/tasks/resque.rake`), load the resque rake tasks:
|
140
127
|
|
141
128
|
``` ruby
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
The following JSON will be stored in the `file_serve` queue:
|
147
|
-
|
148
|
-
``` javascript
|
149
|
-
{
|
150
|
-
'class': 'Archive',
|
151
|
-
'args': [ 44, 'masterbrew' ]
|
152
|
-
}
|
129
|
+
require 'resque'
|
130
|
+
require 'resque/tasks'
|
131
|
+
require 'your/app' # Include this line if you want your workers to have access to your application
|
153
132
|
```
|
154
133
|
|
155
|
-
|
156
|
-
|
157
|
-
So instead of doing this:
|
158
|
-
|
159
|
-
``` ruby
|
160
|
-
Resque.enqueue(Archive, self, branch)
|
161
|
-
```
|
134
|
+
#### Rails
|
162
135
|
|
163
|
-
|
136
|
+
To make resque specific changes, you can override the `resque:setup` job in `lib/tasks` (ex: `lib/tasks/resque.rake`). GitHub's setup task looks like this:
|
164
137
|
|
165
138
|
``` ruby
|
166
|
-
|
139
|
+
task "resque:setup" => :environment do
|
140
|
+
Grit::Git.git_timeout = 10.minutes
|
141
|
+
end
|
167
142
|
```
|
168
143
|
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
While this is less convenient than just sticking a marshaled object
|
173
|
-
in the database, it gives you a slight advantage: your jobs will be
|
174
|
-
run against the most recent version of an object because they need to
|
175
|
-
pull from the DB or cache.
|
176
|
-
|
177
|
-
If your jobs were run against marshaled objects, they could
|
178
|
-
potentially be operating on a stale record with out-of-date information.
|
179
|
-
|
180
|
-
|
181
|
-
### send_later / async
|
182
|
-
|
183
|
-
Want something like DelayedJob's `send_later` or the ability to use
|
184
|
-
instance methods instead of just methods for jobs? See the `examples/`
|
185
|
-
directory for goodies.
|
186
|
-
|
187
|
-
We plan to provide first class `async` support in a future release.
|
188
|
-
|
189
|
-
|
190
|
-
### Failure
|
191
|
-
|
192
|
-
If a job raises an exception, it is logged and handed off to the
|
193
|
-
`Resque::Failure` module. Failures are logged either locally in Redis
|
194
|
-
or using some different backend.
|
195
|
-
|
196
|
-
For example, Resque ships with Hoptoad support.
|
197
|
-
|
198
|
-
Keep this in mind when writing your jobs: you may want to throw
|
199
|
-
exceptions you would not normally throw in order to assist debugging.
|
200
|
-
|
144
|
+
We don't want the `git_timeout` as high as 10 minutes in our web app,
|
145
|
+
but in the Resque workers it's fine.
|
201
146
|
|
202
|
-
Workers
|
203
|
-
|
147
|
+
Running Workers
|
148
|
+
---------------
|
204
149
|
|
205
150
|
Resque workers are rake tasks that run forever. They basically do this:
|
206
151
|
|
@@ -210,79 +155,24 @@ loop do
|
|
210
155
|
if job = reserve
|
211
156
|
job.process
|
212
157
|
else
|
213
|
-
sleep 5 # Polling frequency = 5
|
158
|
+
sleep 5 # Polling frequency = 5
|
214
159
|
end
|
215
160
|
end
|
216
161
|
shutdown
|
217
162
|
```
|
218
163
|
|
219
|
-
Starting a worker is simple
|
220
|
-
|
221
|
-
$ QUEUE=file_serve rake resque:work
|
222
|
-
|
223
|
-
By default Resque won't know about your application's
|
224
|
-
environment. That is, it won't be able to find and run your jobs - it
|
225
|
-
needs to load your application into memory.
|
226
|
-
|
227
|
-
If we've installed Resque as a Rails plugin, we might run this command
|
228
|
-
from our RAILS_ROOT:
|
229
|
-
|
230
|
-
$ QUEUE=file_serve rake environment resque:work
|
231
|
-
|
232
|
-
This will load the environment before starting a worker. Alternately
|
233
|
-
we can define a `resque:setup` task with a dependency on the
|
234
|
-
`environment` rake task:
|
235
|
-
|
236
|
-
``` ruby
|
237
|
-
task "resque:setup" => :environment
|
238
|
-
```
|
239
|
-
|
240
|
-
GitHub's setup task looks like this:
|
241
|
-
|
242
|
-
``` ruby
|
243
|
-
task "resque:setup" => :environment do
|
244
|
-
Grit::Git.git_timeout = 10.minutes
|
245
|
-
end
|
246
|
-
```
|
247
|
-
|
248
|
-
We don't want the `git_timeout` as high as 10 minutes in our web app,
|
249
|
-
but in the Resque workers it's fine.
|
250
|
-
|
251
|
-
|
252
|
-
### Logging
|
164
|
+
Starting a worker is simple:
|
253
165
|
|
254
|
-
|
255
|
-
`VERBOSE` env variable set, they will print basic debugging
|
256
|
-
information. You can also set the `VVERBOSE` (very verbose) env
|
257
|
-
variable.
|
258
|
-
|
259
|
-
$ VVERBOSE=1 QUEUE=file_serve rake environment resque:work
|
260
|
-
|
261
|
-
### Process IDs (PIDs)
|
262
|
-
|
263
|
-
There are scenarios where it's helpful to record the PID of a resque
|
264
|
-
worker process. Use the PIDFILE option for easy access to the PID:
|
265
|
-
|
266
|
-
$ PIDFILE=./resque.pid QUEUE=file_serve rake environment resque:work
|
267
|
-
|
268
|
-
### Running in the background
|
269
|
-
|
270
|
-
(Only supported with ruby >= 1.9). There are scenarios where it's helpful for
|
271
|
-
the resque worker to run itself in the background (usually in combination with
|
272
|
-
PIDFILE). Use the BACKGROUND option so that rake will return as soon as the
|
273
|
-
worker is started.
|
274
|
-
|
275
|
-
$ PIDFILE=./resque.pid BACKGROUND=yes QUEUE=file_serve \
|
276
|
-
rake environment resque:work
|
166
|
+
$ QUEUE=* rake resque:work
|
277
167
|
|
278
|
-
|
168
|
+
Or, you can start multiple workers:
|
279
169
|
|
280
|
-
|
281
|
-
The default is 5 seconds, but for a semi-active app you may want to use a smaller value.
|
170
|
+
$ COUNT=2 QUEUE=* rake resque:workers
|
282
171
|
|
283
|
-
|
172
|
+
This will spawn two Resque workers, each in its own process. Hitting
|
173
|
+
ctrl-c should be sufficient to stop them all.
|
284
174
|
|
285
|
-
|
175
|
+
#### Priorities and Queue Lists
|
286
176
|
|
287
177
|
Resque doesn't support numeric priorities but instead uses the order
|
288
178
|
of queues you give it. We call this list of queues the "queue list."
|
@@ -316,8 +206,7 @@ And workers on our specialized archive machine with this command:
|
|
316
206
|
|
317
207
|
$ QUEUE=archive rake resque:work
|
318
208
|
|
319
|
-
|
320
|
-
### Running All Queues
|
209
|
+
#### Running All Queues
|
321
210
|
|
322
211
|
If you want your workers to work off of every queue, including new
|
323
212
|
queues created on the fly, you can use a splat:
|
@@ -326,113 +215,51 @@ queues created on the fly, you can use a splat:
|
|
326
215
|
|
327
216
|
Queues will be processed in alphabetical order.
|
328
217
|
|
218
|
+
Or, prioritize some queues above `*`:
|
329
219
|
|
330
|
-
|
220
|
+
# QUEUE=critical,* rake resque:work
|
331
221
|
|
332
|
-
|
333
|
-
configuration file is included under `examples/god`. We recommend this
|
334
|
-
method.
|
222
|
+
#### Running All Queues Except for Some
|
335
223
|
|
336
|
-
If you
|
337
|
-
|
224
|
+
If you want your workers to work off of all queues except for some,
|
225
|
+
you can use negation:
|
338
226
|
|
339
|
-
$
|
227
|
+
$ QUEUE=*,!low rake resque:work
|
340
228
|
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
### Forking
|
346
|
-
|
347
|
-
On certain platforms, when a Resque worker reserves a job it
|
348
|
-
immediately forks a child process. The child processes the job then
|
349
|
-
exits. When the child has exited successfully, the worker reserves
|
350
|
-
another job and repeats the process.
|
351
|
-
|
352
|
-
Why?
|
353
|
-
|
354
|
-
Because Resque assumes chaos.
|
355
|
-
|
356
|
-
Resque assumes your background workers will lock up, run too long, or
|
357
|
-
have unwanted memory growth.
|
358
|
-
|
359
|
-
If Resque workers processed jobs themselves, it'd be hard to whip them
|
360
|
-
into shape. Let's say one is using too much memory: you send it a
|
361
|
-
signal that says "shutdown after you finish processing the current
|
362
|
-
job," and it does so. It then starts up again - loading your entire
|
363
|
-
application environment. This adds useless CPU cycles and causes a
|
364
|
-
delay in queue processing.
|
365
|
-
|
366
|
-
Plus, what if it's using too much memory and has stopped responding to
|
367
|
-
signals?
|
368
|
-
|
369
|
-
Thanks to Resque's parent / child architecture, jobs that use too much memory
|
370
|
-
release that memory upon completion. No unwanted growth.
|
371
|
-
|
372
|
-
And what if a job is running too long? You'd need to `kill -9` it then
|
373
|
-
start the worker again. With Resque's parent / child architecture you
|
374
|
-
can tell the parent to forcefully kill the child then immediately
|
375
|
-
start processing more jobs. No startup delay or wasted cycles.
|
376
|
-
|
377
|
-
The parent / child architecture helps us keep tabs on what workers are
|
378
|
-
doing, too. By eliminating the need to `kill -9` workers we can have
|
379
|
-
parents remove themselves from the global listing of workers. If we
|
380
|
-
just ruthlessly killed workers, we'd need a separate watchdog process
|
381
|
-
to add and remove them to the global listing - which becomes
|
382
|
-
complicated.
|
383
|
-
|
384
|
-
Workers instead handle their own state.
|
385
|
-
|
386
|
-
|
387
|
-
### Parents and Children
|
388
|
-
|
389
|
-
Here's a parent / child pair doing some work:
|
390
|
-
|
391
|
-
$ ps -e -o pid,command | grep [r]esque
|
392
|
-
92099 resque: Forked 92102 at 1253142769
|
393
|
-
92102 resque: Processing file_serve since 1253142769
|
394
|
-
|
395
|
-
You can clearly see that process 92099 forked 92102, which has been
|
396
|
-
working since 1253142769.
|
397
|
-
|
398
|
-
(By advertising the time they began processing you can easily use monit
|
399
|
-
or god to kill stale workers.)
|
229
|
+
Negated globs also work. The following will instruct workers to work
|
230
|
+
off of all queues except those beginning with `file_`:
|
400
231
|
|
401
|
-
|
402
|
-
waiting for work on:
|
403
|
-
|
404
|
-
$ ps -e -o pid,command | grep [r]esque
|
405
|
-
92099 resque: Waiting for file_serve,warm_cache
|
232
|
+
$ QUEUE=*,!file_* rake resque:work
|
406
233
|
|
234
|
+
Note that the order in which negated queues are specified does not
|
235
|
+
matter, so `QUEUE=*,!file_*` and `QUEUE=!file_*,*` will have the same
|
236
|
+
effect.
|
407
237
|
|
408
|
-
|
238
|
+
#### Process IDs (PIDs)
|
409
239
|
|
410
|
-
|
240
|
+
There are scenarios where it's helpful to record the PID of a resque
|
241
|
+
worker process. Use the PIDFILE option for easy access to the PID:
|
411
242
|
|
412
|
-
|
413
|
-
* `TERM` / `INT` - Immediately kill child then exit
|
414
|
-
* `USR1` - Immediately kill child but don't exit
|
415
|
-
* `USR2` - Don't start to process any new jobs
|
416
|
-
* `CONT` - Start to process new jobs again after a USR2
|
243
|
+
$ PIDFILE=./resque.pid QUEUE=file_serve rake resque:work
|
417
244
|
|
418
|
-
|
245
|
+
#### Running in the background
|
419
246
|
|
420
|
-
|
421
|
-
|
422
|
-
|
247
|
+
There are scenarios where it's helpful for
|
248
|
+
the resque worker to run itself in the background (usually in combination with
|
249
|
+
PIDFILE). Use the BACKGROUND option so that rake will return as soon as the
|
250
|
+
worker is started.
|
423
251
|
|
424
|
-
|
252
|
+
$ PIDFILE=./resque.pid BACKGROUND=yes QUEUE=file_serve rake resque:work
|
425
253
|
|
426
|
-
|
427
|
-
(for example, to temporarily alleviate load), use `USR2` to stop processing,
|
428
|
-
then `CONT` to start it again.
|
254
|
+
#### Polling frequency
|
429
255
|
|
430
|
-
|
256
|
+
You can pass an INTERVAL option which is a float representing the polling frequency.
|
257
|
+
The default is 5 seconds, but for a semi-active app you may want to use a smaller value.
|
431
258
|
|
432
|
-
|
433
|
-
connection. If that happens we recommend using [this
|
434
|
-
Gist](http://gist.github.com/238999).
|
259
|
+
$ INTERVAL=0.1 QUEUE=file_serve rake resque:work
|
435
260
|
|
261
|
+
When INTERVAL is set to 0 it will run until the queue is empty and then
|
262
|
+
shutdown the worker, instead of waiting for new jobs.
|
436
263
|
|
437
264
|
The Front End
|
438
265
|
-------------
|
@@ -440,9 +267,9 @@ The Front End
|
|
440
267
|
Resque comes with a Sinatra-based front end for seeing what's up with
|
441
268
|
your queue.
|
442
269
|
|
443
|
-
![The Front End](https://
|
270
|
+
![The Front End](https://camo.githubusercontent.com/64d150a243987ffbc33f588bd6d7722a0bb8d69a/687474703a2f2f7475746f7269616c732e6a756d7073746172746c61622e636f6d2f696d616765732f7265737175655f6f766572766965772e706e67)
|
444
271
|
|
445
|
-
|
272
|
+
#### Standalone
|
446
273
|
|
447
274
|
If you've installed Resque as a gem running the front end standalone is easy:
|
448
275
|
|
@@ -465,15 +292,15 @@ or set the Redis connection string if you need to do something like select a dif
|
|
465
292
|
|
466
293
|
$ resque-web -p 8282 -r localhost:6379:2
|
467
294
|
|
468
|
-
|
295
|
+
#### Passenger
|
469
296
|
|
470
297
|
Using Passenger? Resque ships with a `config.ru` you can use. See
|
471
298
|
Phusion's guide:
|
472
299
|
|
473
|
-
Apache: <
|
474
|
-
Nginx: <
|
300
|
+
Apache: <https://www.phusionpassenger.com/library/deploy/apache/deploy/ruby/>
|
301
|
+
Nginx: <https://www.phusionpassenger.com/library/deploy/nginx/deploy/ruby/>
|
475
302
|
|
476
|
-
|
303
|
+
#### Rack::URLMap
|
477
304
|
|
478
305
|
If you want to load Resque on a subpath, possibly alongside other
|
479
306
|
apps, it's easy to do with Rack's `URLMap`:
|
@@ -489,229 +316,151 @@ run Rack::URLMap.new \
|
|
489
316
|
Check `examples/demo/config.ru` for a functional example (including
|
490
317
|
HTTP basic auth).
|
491
318
|
|
492
|
-
|
319
|
+
#### Rails
|
493
320
|
|
494
|
-
You can also mount Resque on a subpath in your existing Rails
|
321
|
+
You can also mount Resque on a subpath in your existing Rails app by adding `require 'resque/server'` to the top of your routes file or in an initializer then adding this to `routes.rb`:
|
495
322
|
|
496
323
|
``` ruby
|
497
324
|
mount Resque::Server.new, :at => "/resque"
|
498
325
|
```
|
499
326
|
|
327
|
+
Jobs
|
328
|
+
----
|
500
329
|
|
501
|
-
|
502
|
-
|
330
|
+
What should you run in the background? Anything that takes any time at
|
331
|
+
all. Slow INSERT statements, disk manipulating, data processing, etc.
|
503
332
|
|
504
|
-
|
505
|
-
over the other?
|
333
|
+
At GitHub we use Resque to process the following types of jobs:
|
506
334
|
|
507
|
-
*
|
508
|
-
*
|
509
|
-
*
|
510
|
-
*
|
511
|
-
*
|
512
|
-
*
|
513
|
-
*
|
514
|
-
*
|
515
|
-
*
|
516
|
-
* DelayedJob can be queried from within your Rails app if you want to
|
517
|
-
add an interface
|
335
|
+
* Warming caches
|
336
|
+
* Counting disk usage
|
337
|
+
* Building tarballs
|
338
|
+
* Building Rubygems
|
339
|
+
* Firing off web hooks
|
340
|
+
* Creating events in the db and pre-caching them
|
341
|
+
* Building graphs
|
342
|
+
* Deleting users
|
343
|
+
* Updating our search index
|
518
344
|
|
519
|
-
|
520
|
-
ActiveRecord. DelayedJob is super easy to setup and works great.
|
521
|
-
GitHub used it for many months to process almost 200 million jobs.
|
345
|
+
As of writing we have about 35 different types of background jobs.
|
522
346
|
|
523
|
-
|
347
|
+
Keep in mind that you don't need a web app to use Resque - we just
|
348
|
+
mention "foreground" and "background" because they make conceptual
|
349
|
+
sense. You could easily be spidering sites and sticking data which
|
350
|
+
needs to be crunched later into a queue.
|
524
351
|
|
525
|
-
|
526
|
-
* You don't care / dislike numeric priorities
|
527
|
-
* You don't need to persist every Ruby object ever
|
528
|
-
* You have potentially huge queues
|
529
|
-
* You want to see what's going on
|
530
|
-
* You expect a lot of failure / chaos
|
531
|
-
* You can setup Redis
|
532
|
-
* You're not running short on RAM
|
352
|
+
#### Persistence
|
533
353
|
|
534
|
-
|
535
|
-
|
536
|
-
* You like numeric priorities
|
537
|
-
* You're not doing a gigantic amount of jobs each day
|
538
|
-
* Your queue stays small and nimble
|
539
|
-
* There is not a lot failure / chaos
|
540
|
-
* You want to easily throw anything on the queue
|
541
|
-
* You don't want to setup Redis
|
542
|
-
|
543
|
-
In no way is Resque a "better" DelayedJob, so make sure you pick the
|
544
|
-
tool that's best for your app.
|
545
|
-
|
546
|
-
|
547
|
-
Installing Redis
|
548
|
-
----------------
|
549
|
-
|
550
|
-
Resque requires Redis 0.900 or higher.
|
551
|
-
|
552
|
-
Resque uses Redis' lists for its queues. It also stores worker state
|
553
|
-
data in Redis.
|
554
|
-
|
555
|
-
#### Homebrew
|
556
|
-
|
557
|
-
If you're on OS X, Homebrew is the simplest way to install Redis:
|
558
|
-
|
559
|
-
$ brew install redis
|
560
|
-
$ redis-server /usr/local/etc/redis.conf
|
561
|
-
|
562
|
-
You now have a Redis daemon running on 6379.
|
563
|
-
|
564
|
-
#### Via Resque
|
565
|
-
|
566
|
-
Resque includes Rake tasks (thanks to Ezra's redis-rb) that will
|
567
|
-
install and run Redis for you:
|
568
|
-
|
569
|
-
$ git clone git://github.com/defunkt/resque.git
|
570
|
-
$ cd resque
|
571
|
-
$ rake redis:install dtach:install
|
572
|
-
$ rake redis:start
|
573
|
-
|
574
|
-
Or, if you don't have admin access on your machine:
|
575
|
-
|
576
|
-
$ git clone git://github.com/defunkt/resque.git
|
577
|
-
$ cd resque
|
578
|
-
$ PREFIX=<your_prefix> rake redis:install dtach:install
|
579
|
-
$ rake redis:start
|
580
|
-
|
581
|
-
You now have Redis running on 6379. Wait a second then hit ctrl-\ to
|
582
|
-
detach and keep it running in the background.
|
583
|
-
|
584
|
-
The demo is probably the best way to figure out how to put the parts
|
585
|
-
together. But, it's not that hard.
|
586
|
-
|
587
|
-
|
588
|
-
Resque Dependencies
|
589
|
-
-------------------
|
590
|
-
|
591
|
-
$ gem install bundler
|
592
|
-
$ bundle install
|
593
|
-
|
594
|
-
|
595
|
-
Installing Resque
|
596
|
-
-----------------
|
597
|
-
|
598
|
-
### In a Rack app, as a gem
|
599
|
-
|
600
|
-
First install the gem.
|
601
|
-
|
602
|
-
$ gem install resque
|
603
|
-
|
604
|
-
Next include it in your application.
|
354
|
+
Jobs are persisted to queues as JSON objects. Let's take our `Archive`
|
355
|
+
example from above. We'll run the following code to create a job:
|
605
356
|
|
606
357
|
``` ruby
|
607
|
-
|
358
|
+
repo = Repository.find(44)
|
359
|
+
repo.async_create_archive('masterbrew')
|
608
360
|
```
|
609
361
|
|
610
|
-
|
362
|
+
The following JSON will be stored in the `file_serve` queue:
|
611
363
|
|
612
|
-
|
364
|
+
``` javascript
|
365
|
+
{
|
366
|
+
'class': 'Archive',
|
367
|
+
'args': [ 44, 'masterbrew' ]
|
368
|
+
}
|
369
|
+
```
|
613
370
|
|
614
|
-
|
371
|
+
Because of this your jobs must only accept arguments that can be JSON encoded.
|
615
372
|
|
616
|
-
|
617
|
-
to an existing Rakefile):
|
373
|
+
So instead of doing this:
|
618
374
|
|
619
375
|
``` ruby
|
620
|
-
|
621
|
-
require 'resque/tasks'
|
376
|
+
Resque.enqueue(Archive, self, branch)
|
622
377
|
```
|
623
378
|
|
624
|
-
|
625
|
-
|
626
|
-
$ QUEUE=* rake resque:work
|
627
|
-
|
628
|
-
Alternately you can define a `resque:setup` hook in your Rakefile if you
|
629
|
-
don't want to load your app every time rake runs.
|
630
|
-
|
631
|
-
|
632
|
-
### In a Rails 2.x app, as a gem
|
633
|
-
|
634
|
-
First install the gem.
|
635
|
-
|
636
|
-
$ gem install resque
|
637
|
-
|
638
|
-
Next include it in your application.
|
639
|
-
|
640
|
-
$ cat config/initializers/load_resque.rb
|
641
|
-
require 'resque'
|
642
|
-
|
643
|
-
Now start your application:
|
644
|
-
|
645
|
-
$ ./script/server
|
646
|
-
|
647
|
-
That's it! You can now create Resque jobs from within your app.
|
648
|
-
|
649
|
-
To start a worker, add this to your Rakefile in `RAILS_ROOT`:
|
379
|
+
do this:
|
650
380
|
|
651
381
|
``` ruby
|
652
|
-
|
382
|
+
Resque.enqueue(Archive, self.id, branch)
|
653
383
|
```
|
654
384
|
|
655
|
-
|
656
|
-
|
657
|
-
$ QUEUE=* rake environment resque:work
|
385
|
+
This is why our above example (and all the examples in `examples/`)
|
386
|
+
uses object IDs instead of passing around the objects.
|
658
387
|
|
659
|
-
|
660
|
-
|
388
|
+
While this is less convenient than just sticking a marshaled object
|
389
|
+
in the database, it gives you a slight advantage: your jobs will be
|
390
|
+
run against the most recent version of an object because they need to
|
391
|
+
pull from the DB or cache.
|
661
392
|
|
393
|
+
If your jobs were run against marshaled objects, they could
|
394
|
+
potentially be operating on a stale record with out-of-date information.
|
662
395
|
|
663
|
-
### In a Rails 2.x app, as a plugin
|
664
396
|
|
665
|
-
|
397
|
+
#### send_later / async
|
666
398
|
|
667
|
-
|
668
|
-
|
399
|
+
Want something like DelayedJob's `send_later` or the ability to use
|
400
|
+
instance methods instead of just methods for jobs? See the `examples/`
|
401
|
+
directory for goodies.
|
669
402
|
|
670
|
-
|
403
|
+
We plan to provide first class `async` support in a future release.
|
671
404
|
|
672
|
-
$ QUEUE=* rake environment resque:work
|
673
405
|
|
674
|
-
|
675
|
-
`lib/tasks/whatever.rake` that loads the `environment` task every time.
|
406
|
+
#### Failure
|
676
407
|
|
408
|
+
If a job raises an exception, it is logged and handed off to the
|
409
|
+
`Resque::Failure` module. Failures are logged either locally in Redis
|
410
|
+
or using some different backend. To see exceptions while developing,
|
411
|
+
see details below under Logging.
|
677
412
|
|
678
|
-
|
413
|
+
For example, Resque ships with Airbrake support. To configure it, put
|
414
|
+
the following into an initialisation file or into your rake job:
|
679
415
|
|
680
|
-
|
416
|
+
``` ruby
|
417
|
+
# send errors which occur in background jobs to redis and airbrake
|
418
|
+
require 'resque/failure/multiple'
|
419
|
+
require 'resque/failure/redis'
|
420
|
+
require 'resque/failure/airbrake'
|
681
421
|
|
682
|
-
|
683
|
-
|
684
|
-
|
685
|
-
...
|
422
|
+
Resque::Failure::Multiple.classes = [Resque::Failure::Redis, Resque::Failure::Airbrake]
|
423
|
+
Resque::Failure.backend = Resque::Failure::Multiple
|
424
|
+
```
|
686
425
|
|
687
|
-
|
426
|
+
Keep this in mind when writing your jobs: you may want to throw
|
427
|
+
exceptions you would not normally throw in order to assist debugging.
|
688
428
|
|
689
|
-
$ bundle install
|
690
429
|
|
691
|
-
|
430
|
+
#### Rails example
|
692
431
|
|
693
|
-
|
432
|
+
If you are using ActiveJob here's how your job definition will look:
|
694
433
|
|
695
|
-
|
434
|
+
``` ruby
|
435
|
+
class ArchiveJob < ApplicationJob
|
436
|
+
queue_as :file_serve
|
696
437
|
|
697
|
-
|
698
|
-
|
438
|
+
def perform(repo_id, branch = 'master')
|
439
|
+
repo = Repository.find(repo_id)
|
440
|
+
repo.create_archive(branch)
|
441
|
+
end
|
442
|
+
end
|
443
|
+
```
|
699
444
|
|
700
445
|
``` ruby
|
701
|
-
|
446
|
+
class Repository
|
447
|
+
def async_create_archive(branch)
|
448
|
+
ArchiveJob.perform_later(self.id, branch)
|
449
|
+
end
|
450
|
+
end
|
702
451
|
```
|
703
452
|
|
704
|
-
|
705
|
-
|
706
|
-
|
707
|
-
|
708
|
-
Don't forget you can define a `resque:setup` hook in
|
709
|
-
`lib/tasks/whatever.rake` that loads the `environment` task every time.
|
453
|
+
It is important to run `ArchiveJob.perform_later(self.id, branch)` rather than `Resque.enqueue(Archive, self.id, branch)`.
|
454
|
+
Otherwise Resque will process the job without actually doing anything.
|
455
|
+
Even if you put an obviously buggy line like `0/0` in the `perform` method,
|
456
|
+
the job will still succeed.
|
710
457
|
|
711
458
|
|
712
459
|
Configuration
|
713
460
|
-------------
|
714
461
|
|
462
|
+
#### Redis
|
463
|
+
|
715
464
|
You may want to change the Redis host and port Resque connects to, or
|
716
465
|
set various other options at startup.
|
717
466
|
|
@@ -733,15 +482,16 @@ Here's our `config/resque.yml`:
|
|
733
482
|
test: localhost:6379
|
734
483
|
staging: redis1.se.github.com:6379
|
735
484
|
fi: localhost:6379
|
736
|
-
production:
|
485
|
+
production: <%= ENV['REDIS_URL'] %>
|
737
486
|
|
738
487
|
And our initializer:
|
739
488
|
|
740
489
|
``` ruby
|
741
490
|
rails_root = ENV['RAILS_ROOT'] || File.dirname(__FILE__) + '/../..'
|
742
491
|
rails_env = ENV['RAILS_ENV'] || 'development'
|
492
|
+
config_file = rails_root + '/config/resque.yml'
|
743
493
|
|
744
|
-
resque_config = YAML.
|
494
|
+
resque_config = YAML::load(ERB.new(IO.read(config_file)).result)
|
745
495
|
Resque.redis = resque_config[rails_env]
|
746
496
|
```
|
747
497
|
|
@@ -759,26 +509,31 @@ For example, if you want to run all jobs in the same process for cucumber, try:
|
|
759
509
|
Resque.inline = ENV['RAILS_ENV'] == "cucumber"
|
760
510
|
```
|
761
511
|
|
512
|
+
#### Logging
|
762
513
|
|
763
|
-
|
764
|
-
-----------------
|
514
|
+
Workers support basic logging to STDOUT.
|
765
515
|
|
766
|
-
|
767
|
-
<http://wiki.github.com/defunkt/resque/plugins>.
|
516
|
+
You can control the logging threshold using `Resque.logger.level`:
|
768
517
|
|
769
|
-
|
770
|
-
|
771
|
-
|
518
|
+
```ruby
|
519
|
+
# config/initializers/resque.rb
|
520
|
+
Resque.logger.level = Logger::DEBUG
|
521
|
+
```
|
772
522
|
|
523
|
+
If you want Resque to log to a file, in Rails do:
|
773
524
|
|
774
|
-
|
775
|
-
|
525
|
+
```ruby
|
526
|
+
# config/initializers/resque.rb
|
527
|
+
Resque.logger = Logger.new(Rails.root.join('log', "#{Rails.env}_resque.log"))
|
528
|
+
```
|
529
|
+
|
530
|
+
#### Namespaces
|
776
531
|
|
777
532
|
If you're running multiple, separate instances of Resque you may want
|
778
533
|
to namespace the keyspaces so they do not overlap. This is not unlike
|
779
534
|
the approach taken by many memcached clients.
|
780
535
|
|
781
|
-
This feature is provided by the [redis-namespace]
|
536
|
+
This feature is provided by the [redis-namespace](http://github.com/resque/redis-namespace) library, which
|
782
537
|
Resque uses by default to separate the keys it manages from other keys
|
783
538
|
in your Redis server.
|
784
539
|
|
@@ -791,38 +546,269 @@ Resque.redis.namespace = "resque:GitHub"
|
|
791
546
|
We recommend sticking this in your initializer somewhere after Redis
|
792
547
|
is configured.
|
793
548
|
|
549
|
+
#### Storing Statistics
|
550
|
+
Resque allows to store count of processed and failed jobs.
|
794
551
|
|
795
|
-
|
796
|
-
----
|
552
|
+
By default it will store it in Redis using the keys `stats:processed` and `stats:failed`.
|
797
553
|
|
798
|
-
|
799
|
-
processed in the background.
|
554
|
+
Some apps would want another stats store, or even a null store:
|
800
555
|
|
801
|
-
|
556
|
+
```ruby
|
557
|
+
# config/initializers/resque.rb
|
558
|
+
class NullDataStore
|
559
|
+
def stat(stat)
|
560
|
+
0
|
561
|
+
end
|
802
562
|
|
563
|
+
def increment_stat(stat, by)
|
564
|
+
end
|
803
565
|
|
804
|
-
|
805
|
-
|
566
|
+
def decrement_stat(stat, by)
|
567
|
+
end
|
806
568
|
|
807
|
-
|
569
|
+
def clear_stat(stat)
|
570
|
+
end
|
571
|
+
end
|
572
|
+
|
573
|
+
Resque.stat_data_store = NullDataStore.new
|
574
|
+
```
|
575
|
+
|
576
|
+
Plugins and Hooks
|
577
|
+
-----------------
|
578
|
+
|
579
|
+
For a list of available plugins see
|
580
|
+
<https://github.com/resque/resque/wiki/plugins>.
|
581
|
+
|
582
|
+
If you'd like to write your own plugin, or want to customize Resque
|
583
|
+
using hooks (such as `Resque.after_fork`), see
|
584
|
+
[docs/HOOKS.md](http://github.com/resque/resque/blob/master/docs/HOOKS.md).
|
585
|
+
|
586
|
+
|
587
|
+
Additional Information
|
588
|
+
----------------------
|
589
|
+
|
590
|
+
#### Resque vs DelayedJob
|
591
|
+
|
592
|
+
How does Resque compare to DelayedJob, and why would you choose one
|
593
|
+
over the other?
|
594
|
+
|
595
|
+
* Resque supports multiple queues
|
596
|
+
* DelayedJob supports finer grained priorities
|
597
|
+
* Resque workers are resilient to memory leaks / bloat
|
598
|
+
* DelayedJob workers are extremely simple and easy to modify
|
599
|
+
* Resque requires Redis
|
600
|
+
* DelayedJob requires ActiveRecord
|
601
|
+
* Resque can only place JSONable Ruby objects on a queue as arguments
|
602
|
+
* DelayedJob can place _any_ Ruby object on its queue as arguments
|
603
|
+
* Resque includes a Sinatra app for monitoring what's going on
|
604
|
+
* DelayedJob can be queried from within your Rails app if you want to
|
605
|
+
add an interface
|
606
|
+
|
607
|
+
If you're doing Rails development, you already have a database and
|
608
|
+
ActiveRecord. DelayedJob is super easy to setup and works great.
|
609
|
+
GitHub used it for many months to process almost 200 million jobs.
|
610
|
+
|
611
|
+
Choose Resque if:
|
612
|
+
|
613
|
+
* You need multiple queues
|
614
|
+
* You don't care / dislike numeric priorities
|
615
|
+
* You don't need to persist every Ruby object ever
|
616
|
+
* You have potentially huge queues
|
617
|
+
* You want to see what's going on
|
618
|
+
* You expect a lot of failure / chaos
|
619
|
+
* You can setup Redis
|
620
|
+
* You're not running short on RAM
|
621
|
+
|
622
|
+
Choose DelayedJob if:
|
623
|
+
|
624
|
+
* You like numeric priorities
|
625
|
+
* You're not doing a gigantic amount of jobs each day
|
626
|
+
* Your queue stays small and nimble
|
627
|
+
* There is not a lot failure / chaos
|
628
|
+
* You want to easily throw anything on the queue
|
629
|
+
* You don't want to setup Redis
|
630
|
+
|
631
|
+
In no way is Resque a "better" DelayedJob, so make sure you pick the
|
632
|
+
tool that's best for your app.
|
633
|
+
|
634
|
+
#### Forking
|
635
|
+
|
636
|
+
On certain platforms, when a Resque worker reserves a job it
|
637
|
+
immediately forks a child process. The child processes the job then
|
638
|
+
exits. When the child has exited successfully, the worker reserves
|
639
|
+
another job and repeats the process.
|
640
|
+
|
641
|
+
Why?
|
642
|
+
|
643
|
+
Because Resque assumes chaos.
|
644
|
+
|
645
|
+
Resque assumes your background workers will lock up, run too long, or
|
646
|
+
have unwanted memory growth.
|
647
|
+
|
648
|
+
If Resque workers processed jobs themselves, it'd be hard to whip them
|
649
|
+
into shape. Let's say one is using too much memory: you send it a
|
650
|
+
signal that says "shutdown after you finish processing the current
|
651
|
+
job," and it does so. It then starts up again - loading your entire
|
652
|
+
application environment. This adds useless CPU cycles and causes a
|
653
|
+
delay in queue processing.
|
654
|
+
|
655
|
+
Plus, what if it's using too much memory and has stopped responding to
|
656
|
+
signals?
|
657
|
+
|
658
|
+
Thanks to Resque's parent / child architecture, jobs that use too much memory
|
659
|
+
release that memory upon completion. No unwanted growth.
|
660
|
+
|
661
|
+
And what if a job is running too long? You'd need to `kill -9` it then
|
662
|
+
start the worker again. With Resque's parent / child architecture you
|
663
|
+
can tell the parent to forcefully kill the child then immediately
|
664
|
+
start processing more jobs. No startup delay or wasted cycles.
|
665
|
+
|
666
|
+
The parent / child architecture helps us keep tabs on what workers are
|
667
|
+
doing, too. By eliminating the need to `kill -9` workers we can have
|
668
|
+
parents remove themselves from the global listing of workers. If we
|
669
|
+
just ruthlessly killed workers, we'd need a separate watchdog process
|
670
|
+
to add and remove them to the global listing - which becomes
|
671
|
+
complicated.
|
672
|
+
|
673
|
+
Workers instead handle their own state.
|
674
|
+
|
675
|
+
#### `at_exit` Callbacks
|
676
|
+
|
677
|
+
Resque uses `Kernel#exit!` for exiting its workers' child processes. So any `at_exit` callback defined in your application won't be executed when the job is finished and the child process exits.
|
678
|
+
|
679
|
+
You can alter this behavior by setting the `RUN_AT_EXIT_HOOKS` environment variable.
|
680
|
+
|
681
|
+
#### Parents and Children
|
682
|
+
|
683
|
+
Here's a parent / child pair doing some work:
|
684
|
+
|
685
|
+
$ ps -e -o pid,command | grep [r]esque
|
686
|
+
92099 resque: Forked 92102 at 1253142769
|
687
|
+
92102 resque: Processing file_serve since 1253142769
|
688
|
+
|
689
|
+
You can clearly see that process 92099 forked 92102, which has been
|
690
|
+
working since 1253142769.
|
691
|
+
|
692
|
+
(By advertising the time they began processing you can easily use monit
|
693
|
+
or god to kill stale workers.)
|
694
|
+
|
695
|
+
When a parent process is idle, it lets you know what queues it is
|
696
|
+
waiting for work on:
|
697
|
+
|
698
|
+
$ ps -e -o pid,command | grep [r]esque
|
699
|
+
92099 resque: Waiting for file_serve,warm_cache
|
700
|
+
|
701
|
+
|
702
|
+
#### Signals
|
703
|
+
|
704
|
+
Resque workers respond to a few different signals:
|
705
|
+
|
706
|
+
* `QUIT` - Wait for child to finish processing then exit
|
707
|
+
* `TERM` / `INT` - Immediately kill child then exit
|
708
|
+
* `USR1` - Immediately kill child but don't exit
|
709
|
+
* `USR2` - Don't start to process any new jobs
|
710
|
+
* `CONT` - Start to process new jobs again after a USR2
|
711
|
+
|
712
|
+
If you want to gracefully shutdown a Resque worker, use `QUIT`.
|
713
|
+
|
714
|
+
If you want to kill a stale or stuck child, use `USR1`. Processing
|
715
|
+
will continue as normal unless the child was not found. In that case
|
716
|
+
Resque assumes the parent process is in a bad state and shuts down.
|
717
|
+
|
718
|
+
If you want to kill a stale or stuck child and shutdown, use `TERM`
|
719
|
+
|
720
|
+
If you want to stop processing jobs, but want to leave the worker running
|
721
|
+
(for example, to temporarily alleviate load), use `USR2` to stop processing,
|
722
|
+
then `CONT` to start it again. It's also possible to [pause all workers](#pausing-all-workers).
|
723
|
+
|
724
|
+
#### Heroku
|
725
|
+
|
726
|
+
When shutting down processes, Heroku sends every process a TERM signal at the
|
727
|
+
same time. By default this causes an immediate shutdown of any running job
|
728
|
+
leading to frequent `Resque::TermException` errors. For short running jobs, a simple
|
729
|
+
solution is to give a small amount of time for the job to finish
|
730
|
+
before killing it.
|
731
|
+
|
732
|
+
Resque doesn't handle this out of the box (for both cedar-14 and heroku-16), you need to
|
733
|
+
install the [`resque-heroku-signals`](https://github.com/iloveitaly/resque-heroku-signals)
|
734
|
+
addon which adds the required signal handling to make the behavior described above work.
|
735
|
+
Related issue: https://github.com/resque/resque/issues/1559
|
736
|
+
|
737
|
+
To accomplish this set the following environment variables:
|
738
|
+
|
739
|
+
* `RESQUE_PRE_SHUTDOWN_TIMEOUT` - The time between the parent receiving a shutdown signal (TERM by default) and it sending that signal on to the child process. Designed to give the child process
|
740
|
+
time to complete before being forced to die.
|
741
|
+
|
742
|
+
* `TERM_CHILD` - Must be set for `RESQUE_PRE_SHUTDOWN_TIMEOUT` to be used. After the timeout, if the child is still running it will raise a `Resque::TermException` and exit.
|
743
|
+
|
744
|
+
* `RESQUE_TERM_TIMEOUT` - By default you have a few seconds to handle `Resque::TermException` in your job. `RESQUE_TERM_TIMEOUT` and `RESQUE_PRE_SHUTDOWN_TIMEOUT` must be lower than the [heroku dyno timeout](https://devcenter.heroku.com/articles/limits#exit-timeout).
|
745
|
+
|
746
|
+
#### Pausing all workers
|
747
|
+
|
748
|
+
Workers will not process pending jobs if the Redis key `pause-all-workers` is set with the string value "true".
|
749
|
+
|
750
|
+
``` ruby
|
751
|
+
Resque.redis.set('pause-all-workers', 'true')
|
752
|
+
```
|
753
|
+
|
754
|
+
Nothing happens to jobs that are already being processed by workers.
|
755
|
+
|
756
|
+
Unpause by removing the Redis key `pause-all-workers`.
|
757
|
+
|
758
|
+
``` ruby
|
759
|
+
Resque.redis.del('pause-all-workers')
|
760
|
+
```
|
761
|
+
|
762
|
+
#### Monitoring
|
763
|
+
|
764
|
+
##### god
|
808
765
|
|
809
766
|
If you're using god to monitor Resque, we have provided example
|
810
767
|
configs in `examples/god/`. One is for starting / stopping workers,
|
811
768
|
the other is for killing workers that have been running too long.
|
812
769
|
|
813
|
-
|
770
|
+
##### monit
|
814
771
|
|
815
772
|
If you're using monit, `examples/monit/resque.monit` is provided free
|
816
773
|
of charge. This is **not** used by GitHub in production, so please
|
817
774
|
send patches for any tweaks or improvements you can make to it.
|
818
775
|
|
776
|
+
#### Mysql::Error: MySQL server has gone away
|
819
777
|
|
820
|
-
|
821
|
-
---------
|
778
|
+
If your workers remain idle for too long they may lose their MySQL connection. Depending on your version of Rails, we recommend the following:
|
822
779
|
|
823
|
-
|
824
|
-
|
780
|
+
##### Rails
|
781
|
+
In your `perform` method, add the following line:
|
825
782
|
|
783
|
+
``` ruby
|
784
|
+
class MyTask
|
785
|
+
def self.perform
|
786
|
+
ActiveRecord::Base.verify_active_connections!
|
787
|
+
# rest of your code
|
788
|
+
end
|
789
|
+
end
|
790
|
+
```
|
791
|
+
|
792
|
+
The Rails doc says the following about `verify_active_connections!`:
|
793
|
+
|
794
|
+
Verify active connections and remove and disconnect connections associated with stale threads.
|
795
|
+
|
796
|
+
##### Rails 4.x
|
797
|
+
|
798
|
+
In your `perform` method, instead of `verify_active_connections!`, use:
|
799
|
+
|
800
|
+
``` ruby
|
801
|
+
class MyTask
|
802
|
+
def self.perform
|
803
|
+
ActiveRecord::Base.clear_active_connections!
|
804
|
+
# rest of your code
|
805
|
+
end
|
806
|
+
end
|
807
|
+
```
|
808
|
+
|
809
|
+
From the Rails docs on [`clear_active_connections!`](http://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/ConnectionHandler.html#method-i-clear_active_connections-21):
|
810
|
+
|
811
|
+
Returns any connections in use by the current thread back to the pool, and also returns connections to the pool cached by threads that are no longer alive.
|
826
812
|
|
827
813
|
Development
|
828
814
|
-----------
|
@@ -831,7 +817,7 @@ Want to hack on Resque?
|
|
831
817
|
|
832
818
|
First clone the repo and run the tests:
|
833
819
|
|
834
|
-
git clone git://github.com/
|
820
|
+
git clone git://github.com/resque/resque.git
|
835
821
|
cd resque
|
836
822
|
rake test
|
837
823
|
|
@@ -853,56 +839,40 @@ it:
|
|
853
839
|
If you get an error requiring any of the dependencies, you may have
|
854
840
|
failed to install them or be seeing load path issues.
|
855
841
|
|
856
|
-
|
857
|
-
|
842
|
+
#### Demo
|
843
|
+
Resque ships with a demo Sinatra app for creating jobs that are later
|
844
|
+
processed in the background.
|
858
845
|
|
846
|
+
Try it out by looking at the README, found at `examples/demo/README.markdown`.
|
859
847
|
|
860
|
-
Contributing
|
861
|
-
------------
|
848
|
+
#### Contributing
|
862
849
|
|
863
|
-
Read
|
850
|
+
Read [CONTRIBUTING.md](CONTRIBUTING.md) first.
|
864
851
|
|
865
852
|
Once you've made your great commits:
|
866
853
|
|
867
|
-
1. [Fork]
|
854
|
+
1. [Fork](http://help.github.com/forking/) Resque
|
868
855
|
2. Create a topic branch - `git checkout -b my_branch`
|
869
856
|
3. Push to your branch - `git push origin my_branch`
|
870
857
|
4. Create a [Pull Request](http://help.github.com/pull-requests/) from your branch
|
871
|
-
5. That's it!
|
872
|
-
|
873
|
-
|
874
|
-
Mailing List
|
875
|
-
------------
|
876
|
-
|
877
|
-
To join the list simply send an email to <resque@librelist.com>. This
|
878
|
-
will subscribe you and send you information about your subscription,
|
879
|
-
including unsubscribe information.
|
880
858
|
|
881
|
-
|
859
|
+
Questions
|
860
|
+
---------
|
882
861
|
|
862
|
+
Please add them to the [FAQ](https://github.com/resque/resque/wiki/FAQ) or open an issue on this repo.
|
883
863
|
|
884
864
|
Meta
|
885
865
|
----
|
886
866
|
|
887
|
-
* Code: `git clone git://github.com/
|
888
|
-
* Home: <http://github.com/
|
889
|
-
* Docs: <http://
|
890
|
-
* Bugs: <http://github.com/
|
891
|
-
*
|
892
|
-
* Chat: <irc://irc.freenode.net/resque>
|
893
|
-
* Gems: <http://gemcutter.org/gems/resque>
|
894
|
-
|
895
|
-
This project uses [Semantic Versioning][sv].
|
867
|
+
* Code: `git clone git://github.com/resque/resque.git`
|
868
|
+
* Home: <http://github.com/resque/resque>
|
869
|
+
* Docs: <http://rubydoc.info/gems/resque>
|
870
|
+
* Bugs: <http://github.com/resque/resque/issues>
|
871
|
+
* Gems: <https://rubygems.org/gems/resque>
|
896
872
|
|
873
|
+
This project uses [Semantic Versioning](http://semver.org/)
|
897
874
|
|
898
875
|
Author
|
899
876
|
------
|
900
877
|
|
901
878
|
Chris Wanstrath :: chris@ozmm.org :: @defunkt
|
902
|
-
|
903
|
-
[0]: http://github.com/blog/542-introducing-resque
|
904
|
-
[1]: http://help.github.com/forking/
|
905
|
-
[2]: http://github.com/defunkt/resque/issues
|
906
|
-
[sv]: http://semver.org/
|
907
|
-
[rs]: http://github.com/defunkt/redis-namespace
|
908
|
-
[cb]: http://wiki.github.com/defunkt/resque/contributing
|