resque 1.11.0 → 1.12.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of resque might be problematic. Click here for more details.
- data/HISTORY.md +9 -0
- data/LICENSE +1 -1
- data/README.markdown +13 -4
- data/lib/resque/failure/hoptoad.rb +11 -5
- data/lib/resque/server.rb +2 -2
- data/lib/resque/server/views/queues.erb +1 -1
- data/lib/resque/server/views/workers.erb +2 -2
- data/lib/resque/tasks.rb +4 -1
- data/lib/resque/version.rb +1 -1
- data/lib/resque/worker.rb +23 -5
- data/tasks/redis.rake +22 -20
- data/test/test_helper.rb +14 -0
- data/test/worker_test.rb +17 -0
- metadata +3 -3
data/HISTORY.md
CHANGED
@@ -1,3 +1,12 @@
|
|
1
|
+
## 1.12.0 (2011-02-03)
|
2
|
+
|
3
|
+
* Added pidfile writing from `rake resque:work`
|
4
|
+
* Added Worker#pid method
|
5
|
+
* Added configurable location for `rake install`
|
6
|
+
* Bugfix: Errors in failure backend are rescue'd
|
7
|
+
* Bugfix: Non-working workers no longer counted in "working" count
|
8
|
+
* Bugfix: Don't think resque-web is a worker
|
9
|
+
|
1
10
|
## 1.11.0 (2010-08-23)
|
2
11
|
|
3
12
|
* Web UI: Group /workers page by hostnames
|
data/LICENSE
CHANGED
data/README.markdown
CHANGED
@@ -1,8 +1,9 @@
|
|
1
1
|
Resque
|
2
2
|
======
|
3
3
|
|
4
|
-
Resque is a Redis-backed library for creating
|
5
|
-
those jobs on multiple queues, and processing
|
4
|
+
Resque (pronounced like "rescue") is a Redis-backed library for creating
|
5
|
+
background jobs, placing those jobs on multiple queues, and processing
|
6
|
+
them later.
|
6
7
|
|
7
8
|
Background jobs can be any Ruby class or module that responds to
|
8
9
|
`perform`. Your existing classes can easily be converted to background
|
@@ -234,6 +235,13 @@ variable.
|
|
234
235
|
|
235
236
|
$ VVERBOSE=1 QUEUE=file_serve rake environment resque:work
|
236
237
|
|
238
|
+
### Process IDs (PIDs)
|
239
|
+
|
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:
|
242
|
+
|
243
|
+
$ PIDFILE=./resque.pid QUEUE=file_serve rake environment resque:work
|
244
|
+
|
237
245
|
|
238
246
|
### Priorities and Queue Lists
|
239
247
|
|
@@ -419,7 +427,8 @@ You can also set the namespace directly using `resque-web`:
|
|
419
427
|
Using Passenger? Resque ships with a `config.ru` you can use. See
|
420
428
|
Phusion's guide:
|
421
429
|
|
422
|
-
<http://www.modrails.com/documentation/Users%20guide.html#_deploying_a_rack_based_ruby_application>
|
430
|
+
Apache: <http://www.modrails.com/documentation/Users%20guide%20Apache.html#_deploying_a_rack_based_ruby_application>
|
431
|
+
Nginx: <http://www.modrails.com/documentation/Users%20guide%20Nginx.html#deploying_a_rack_app>
|
423
432
|
|
424
433
|
### Rack::URLMap
|
425
434
|
|
@@ -764,7 +773,7 @@ To join the list simply send an email to <resque@librelist.com>. This
|
|
764
773
|
will subscribe you and send you information about your subscription,
|
765
774
|
including unsubscribe information.
|
766
775
|
|
767
|
-
The archive can be found at <http://librelist.com/browser/>.
|
776
|
+
The archive can be found at <http://librelist.com/browser/resque/>.
|
768
777
|
|
769
778
|
|
770
779
|
Meta
|
@@ -26,8 +26,11 @@ module Resque
|
|
26
26
|
INPUT_FORMAT = /^([^:]+):(\d+)(?::in `([^']+)')?$/
|
27
27
|
|
28
28
|
class << self
|
29
|
-
attr_accessor :secure, :api_key
|
29
|
+
attr_accessor :secure, :api_key
|
30
|
+
attr_accessor :proxy_host, :proxy_port, :proxy_user, :proxy_pass
|
30
31
|
attr_accessor :server_environment
|
32
|
+
attr_accessor :host, :port
|
33
|
+
attr_accessor :http_read_timeout, :http_open_timeout
|
31
34
|
end
|
32
35
|
|
33
36
|
def self.count
|
@@ -43,17 +46,20 @@ module Resque
|
|
43
46
|
|
44
47
|
def save
|
45
48
|
http = use_ssl? ? :https : :http
|
46
|
-
|
49
|
+
host = self.class.host || 'hoptoadapp.com'
|
50
|
+
port = self.class.port
|
51
|
+
url = URI.parse("#{http}://#{host}:#{port}/notifier_api/v2/notices/")
|
47
52
|
|
48
|
-
request = Net::HTTP::Proxy
|
53
|
+
request = Net::HTTP::Proxy self.class.proxy_host, self.class.proxy_port,
|
54
|
+
self.class.proxy_user, self.class.proxy_pass
|
49
55
|
http = request.new(url.host, url.port)
|
50
56
|
headers = {
|
51
57
|
'Content-type' => 'text/xml',
|
52
58
|
'Accept' => 'text/xml, application/xml'
|
53
59
|
}
|
54
60
|
|
55
|
-
http.read_timeout = 5 # seconds
|
56
|
-
http.open_timeout = 2 # seconds
|
61
|
+
http.read_timeout = self.class.http_read_timeout || 5 # seconds
|
62
|
+
http.open_timeout = self.class.http_open_timeout || 2 # seconds
|
57
63
|
|
58
64
|
http.use_ssl = use_ssl?
|
59
65
|
|
data/lib/resque/server.rb
CHANGED
@@ -147,7 +147,7 @@ module Resque
|
|
147
147
|
|
148
148
|
%w( overview workers ).each do |page|
|
149
149
|
get "/#{page}.poll" do
|
150
|
-
content_type "text/
|
150
|
+
content_type "text/html"
|
151
151
|
@polling = true
|
152
152
|
show(page.to_sym, false).gsub(/\s{1,}/, ' ')
|
153
153
|
end
|
@@ -201,7 +201,7 @@ module Resque
|
|
201
201
|
stats << "queues.#{queue}=#{Resque.size(queue)}"
|
202
202
|
end
|
203
203
|
|
204
|
-
content_type 'text/
|
204
|
+
content_type 'text/html'
|
205
205
|
stats.join "\n"
|
206
206
|
end
|
207
207
|
|
@@ -85,7 +85,7 @@
|
|
85
85
|
<%=poll%>
|
86
86
|
|
87
87
|
<% else %>
|
88
|
-
|
88
|
+
<% @subtabs = [] %>
|
89
89
|
<h1 class='wi'>Workers</h1>
|
90
90
|
<p class='intro'>The hostnames below all have registered workers. Select a hostname to view its workers, or "all" to see all workers.</p>
|
91
91
|
<table class='queues'>
|
@@ -93,7 +93,7 @@
|
|
93
93
|
<th>Hostname</th>
|
94
94
|
<th>Workers</th>
|
95
95
|
</tr>
|
96
|
-
<% for hostname, workers in worker_hosts %>
|
96
|
+
<% for hostname, workers in worker_hosts.sort_by { |h,w| h } %>
|
97
97
|
<tr>
|
98
98
|
<td class='queue'><a class="queue" href="<%= url "workers/#{hostname}" %>"><%= hostname %></a></td>
|
99
99
|
<td class='size'><%= workers.size %></td>
|
data/lib/resque/tasks.rb
CHANGED
@@ -8,7 +8,6 @@ namespace :resque do
|
|
8
8
|
task :work => :setup do
|
9
9
|
require 'resque'
|
10
10
|
|
11
|
-
worker = nil
|
12
11
|
queues = (ENV['QUEUES'] || ENV['QUEUE']).to_s.split(',')
|
13
12
|
|
14
13
|
begin
|
@@ -19,6 +18,10 @@ namespace :resque do
|
|
19
18
|
abort "set QUEUE env var, e.g. $ QUEUE=critical,high rake resque:work"
|
20
19
|
end
|
21
20
|
|
21
|
+
if ENV['PIDFILE']
|
22
|
+
File.open(ENV['PIDFILE'], 'w') { |f| f << Process.pid.to_s }
|
23
|
+
end
|
24
|
+
|
22
25
|
worker.log "Starting worker #{worker}"
|
23
26
|
|
24
27
|
worker.work(ENV['INTERVAL'] || 5) # interval, will block
|
data/lib/resque/version.rb
CHANGED
data/lib/resque/worker.rb
CHANGED
@@ -32,8 +32,13 @@ module Resque
|
|
32
32
|
def self.working
|
33
33
|
names = all
|
34
34
|
return [] unless names.any?
|
35
|
+
|
35
36
|
names.map! { |name| "worker:#{name}" }
|
36
|
-
|
37
|
+
|
38
|
+
reportedly_working = redis.mapped_mget(*names).reject do |key, value|
|
39
|
+
value.nil?
|
40
|
+
end
|
41
|
+
reportedly_working.keys.map do |key|
|
37
42
|
find key.sub("worker:", '')
|
38
43
|
end.compact
|
39
44
|
end
|
@@ -73,7 +78,7 @@ module Resque
|
|
73
78
|
# in alphabetical order. Queues can be dynamically added or
|
74
79
|
# removed without needing to restart workers using this method.
|
75
80
|
def initialize(*queues)
|
76
|
-
@queues = queues
|
81
|
+
@queues = queues.map { |queue| queue.to_s.strip }
|
77
82
|
validate_queues
|
78
83
|
end
|
79
84
|
|
@@ -157,7 +162,11 @@ module Resque
|
|
157
162
|
job.perform
|
158
163
|
rescue Object => e
|
159
164
|
log "#{job.inspect} failed: #{e.inspect}"
|
160
|
-
|
165
|
+
begin
|
166
|
+
job.fail(e)
|
167
|
+
rescue Object => e
|
168
|
+
log "Received exception when reporting failure: #{e.inspect}"
|
169
|
+
end
|
161
170
|
failed!
|
162
171
|
else
|
163
172
|
log "done: #{job.inspect}"
|
@@ -178,6 +187,10 @@ module Resque
|
|
178
187
|
end
|
179
188
|
|
180
189
|
nil
|
190
|
+
rescue Exception => e
|
191
|
+
log "Error reserving job: #{e.inspect}"
|
192
|
+
log e.backtrace.join("\n")
|
193
|
+
raise e
|
181
194
|
end
|
182
195
|
|
183
196
|
# Returns a list of queues to use when searching for a job.
|
@@ -440,7 +453,7 @@ module Resque
|
|
440
453
|
# The string representation is the same as the id for this worker
|
441
454
|
# instance. Can be used with `Worker.find`.
|
442
455
|
def to_s
|
443
|
-
@to_s ||= "#{hostname}:#{
|
456
|
+
@to_s ||= "#{hostname}:#{pid}:#{@queues.join(',')}"
|
444
457
|
end
|
445
458
|
alias_method :id, :to_s
|
446
459
|
|
@@ -449,10 +462,15 @@ module Resque
|
|
449
462
|
@hostname ||= `hostname`.chomp
|
450
463
|
end
|
451
464
|
|
465
|
+
# Returns PID of running worker
|
466
|
+
def pid
|
467
|
+
@pid ||= Process.pid
|
468
|
+
end
|
469
|
+
|
452
470
|
# Returns an array of string pids of all the other workers on this
|
453
471
|
# machine. Useful when pruning dead workers on startup.
|
454
472
|
def worker_pids
|
455
|
-
`ps -A -o pid,command | grep [r]esque`.split("\n").map do |line|
|
473
|
+
`ps -A -o pid,command | grep [r]esque | grep -i "resque-web"`.split("\n").map do |line|
|
456
474
|
line.split(' ')[0]
|
457
475
|
end
|
458
476
|
end
|
data/tasks/redis.rake
CHANGED
@@ -4,7 +4,6 @@ require 'open-uri'
|
|
4
4
|
require 'pathname'
|
5
5
|
|
6
6
|
class RedisRunner
|
7
|
-
|
8
7
|
def self.redis_dir
|
9
8
|
@redis_dir ||= if ENV['PREFIX']
|
10
9
|
Pathname.new(ENV['PREFIX'])
|
@@ -48,11 +47,11 @@ class RedisRunner
|
|
48
47
|
def self.stop
|
49
48
|
sh 'echo "SHUTDOWN" | nc localhost 6379'
|
50
49
|
end
|
51
|
-
|
52
50
|
end
|
53
51
|
|
54
|
-
|
52
|
+
INSTALL_DIR = ENV['INSTALL_DIR'] || '/tmp/redis'
|
55
53
|
|
54
|
+
namespace :redis do
|
56
55
|
desc 'About redis'
|
57
56
|
task :about do
|
58
57
|
puts "\nSee http://code.google.com/p/redis/ for information about redis.\n\n"
|
@@ -79,7 +78,12 @@ namespace :redis do
|
|
79
78
|
RedisRunner.attach
|
80
79
|
end
|
81
80
|
|
82
|
-
desc
|
81
|
+
desc <<-DOC
|
82
|
+
Install the latest verison of Redis from Github (requires git, duh).
|
83
|
+
Use INSTALL_DIR env var like "rake redis:install INSTALL_DIR=~/tmp"
|
84
|
+
in order to get an alternate location for your install files.
|
85
|
+
DOC
|
86
|
+
|
83
87
|
task :install => [:about, :download, :make] do
|
84
88
|
bin_dir = '/usr/bin'
|
85
89
|
conf_dir = '/etc'
|
@@ -93,33 +97,31 @@ namespace :redis do
|
|
93
97
|
end
|
94
98
|
|
95
99
|
%w(redis-benchmark redis-cli redis-server).each do |bin|
|
96
|
-
sh "cp /
|
100
|
+
sh "cp #{INSTALL_DIR}/src/#{bin} #{bin_dir}"
|
97
101
|
end
|
98
102
|
|
99
103
|
puts "Installed redis-benchmark, redis-cli and redis-server to #{bin_dir}"
|
100
104
|
|
101
105
|
unless File.exists?("#{conf_dir}/redis.conf")
|
102
|
-
sh "cp /
|
106
|
+
sh "cp #{INSTALL_DIR}/redis.conf #{conf_dir}/redis.conf"
|
103
107
|
puts "Installed redis.conf to #{conf_dir} \n You should look at this file!"
|
104
108
|
end
|
105
109
|
end
|
106
110
|
|
107
111
|
task :make do
|
108
|
-
sh "cd /
|
109
|
-
sh "cd /
|
112
|
+
sh "cd #{INSTALL_DIR}/src && make clean"
|
113
|
+
sh "cd #{INSTALL_DIR}/src && make"
|
110
114
|
end
|
111
115
|
|
112
116
|
desc "Download package"
|
113
117
|
task :download do
|
114
|
-
sh
|
115
|
-
sh
|
116
|
-
sh "cd
|
118
|
+
sh "rm -rf #{INSTALL_DIR}/" if File.exists?("#{INSTALL_DIR}/.svn")
|
119
|
+
sh "git clone git://github.com/antirez/redis.git #{INSTALL_DIR}" unless File.exists?(INSTALL_DIR)
|
120
|
+
sh "cd #{INSTALL_DIR} && git pull" if File.exists?("#{INSTALL_DIR}/.git")
|
117
121
|
end
|
118
|
-
|
119
122
|
end
|
120
123
|
|
121
124
|
namespace :dtach do
|
122
|
-
|
123
125
|
desc 'About dtach'
|
124
126
|
task :about do
|
125
127
|
puts "\nSee http://dtach.sourceforge.net/ for information about dtach.\n\n"
|
@@ -130,30 +132,30 @@ namespace :dtach do
|
|
130
132
|
|
131
133
|
bin_dir = "/usr/bin"
|
132
134
|
|
135
|
+
|
133
136
|
if ENV['PREFIX']
|
134
137
|
bin_dir = "#{ENV['PREFIX']}/bin"
|
135
138
|
sh "mkdir -p #{bin_dir}" unless File.exists?("#{bin_dir}")
|
136
139
|
end
|
137
140
|
|
138
|
-
sh "cp /
|
141
|
+
sh "cp #{INSTALL_DIR}/dtach-0.8/dtach #{bin_dir}"
|
139
142
|
end
|
140
143
|
|
141
144
|
task :make do
|
142
|
-
sh
|
145
|
+
sh "cd #{INSTALL_DIR}/dtach-0.8/ && ./configure && make"
|
143
146
|
end
|
144
147
|
|
145
148
|
desc "Download package"
|
146
149
|
task :download do
|
147
|
-
unless File.exists?(
|
150
|
+
unless File.exists?("#{INSTALL_DIR}/dtach-0.8.tar.gz")
|
148
151
|
require 'net/http'
|
149
152
|
|
150
153
|
url = 'http://downloads.sourceforge.net/project/dtach/dtach/0.8/dtach-0.8.tar.gz'
|
151
|
-
open(
|
154
|
+
open("#{INSTALL_DIR}/dtach-0.8.tar.gz", 'wb') do |file| file.write(open(url).read) end
|
152
155
|
end
|
153
156
|
|
154
|
-
unless File.directory?(
|
155
|
-
sh
|
157
|
+
unless File.directory?("#{INSTALL_DIR}/dtach-0.8")
|
158
|
+
sh "cd #{INSTALL_DIR} && tar xzf dtach-0.8.tar.gz"
|
156
159
|
end
|
157
160
|
end
|
158
161
|
end
|
159
|
-
|
data/test/test_helper.rb
CHANGED
@@ -114,3 +114,17 @@ class BadJobWithSyntaxError
|
|
114
114
|
raise SyntaxError, "Extra Bad job!"
|
115
115
|
end
|
116
116
|
end
|
117
|
+
|
118
|
+
class BadFailureBackend < Resque::Failure::Base
|
119
|
+
def save
|
120
|
+
raise Exception.new("Failure backend error")
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
def with_failure_backend(failure_backend, &block)
|
125
|
+
previous_backend = Resque::Failure.backend
|
126
|
+
Resque::Failure.backend = failure_backend
|
127
|
+
yield block
|
128
|
+
ensure
|
129
|
+
Resque::Failure.backend = previous_backend
|
130
|
+
end
|
data/test/worker_test.rb
CHANGED
@@ -25,6 +25,13 @@ context "Resque::Worker" do
|
|
25
25
|
assert_equal('Extra Bad job!', Resque::Failure.all['error'])
|
26
26
|
end
|
27
27
|
|
28
|
+
test "does not allow exceptions from failure backend to escape" do
|
29
|
+
job = Resque::Job.new(:jobs, {})
|
30
|
+
with_failure_backend BadFailureBackend do
|
31
|
+
@worker.perform job
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
28
35
|
test "fails uncompleted jobs on exit" do
|
29
36
|
job = Resque::Job.new(:jobs, [GoodJob, "blah"])
|
30
37
|
@worker.working_on(job)
|
@@ -57,6 +64,12 @@ context "Resque::Worker" do
|
|
57
64
|
assert_equal 2, Resque::Failure.count
|
58
65
|
end
|
59
66
|
|
67
|
+
test "strips whitespace from queue names" do
|
68
|
+
queues = "critical, high, low".split(',')
|
69
|
+
worker = Resque::Worker.new(*queues)
|
70
|
+
assert_equal %w( critical high low ), worker.queues
|
71
|
+
end
|
72
|
+
|
60
73
|
test "can work on multiple queues" do
|
61
74
|
Resque::Job.create(:high, GoodJob)
|
62
75
|
Resque::Job.create(:critical, GoodJob)
|
@@ -299,4 +312,8 @@ context "Resque::Worker" do
|
|
299
312
|
workerA.work(0)
|
300
313
|
assert $AFTER_FORK_CALLED
|
301
314
|
end
|
315
|
+
|
316
|
+
test "returns PID of running process" do
|
317
|
+
assert_equal Process.pid, @worker.pid
|
318
|
+
end
|
302
319
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: resque
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 39
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 1
|
8
|
-
-
|
8
|
+
- 12
|
9
9
|
- 0
|
10
|
-
version: 1.
|
10
|
+
version: 1.12.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Chris Wanstrath
|