Skip to content

Commit 56ca6ab

Browse files
committed
Merge pull request resque#671 from steveklabnik/mother_of_all_pull_requests
Mother of all pull requests
2 parents 6aeccc3 + 75a6204 commit 56ca6ab

File tree

17 files changed

+283
-81
lines changed

17 files changed

+283
-81
lines changed

README.markdown

Lines changed: 119 additions & 6 deletions
Large diffs are not rendered by default.

examples/demo/README.markdown

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ pending jobs rising.
2222
Now in another shell terminal start the worker:
2323

2424
$ cd resque/examples/demo
25-
$ VERBOSE=true QUEUE=default rake resque:work
25+
$ VERBOSE=true QUEUE=default,failing rake resque:work
2626

2727
You should see the following output:
2828

@@ -33,7 +33,7 @@ You should see the following output:
3333

3434
You can also use `VVERBOSE` (very verbose) if you want to see more:
3535

36-
$ VVERBOSE=true QUEUE=default rake resque:work
36+
$ VERBOSE=true QUEUE=default,failing rake resque:work
3737
*** Starting worker hostname:90399:default
3838
** [05:55:09 2009-09-16] 90399: Registered signals
3939
** [05:55:09 2009-09-16] 90399: Checking default

examples/god/stale.god

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,22 @@
22
# processes. Their sacrifice is for the greater good.
33

44
WORKER_TIMEOUT = 60 * 10 # 10 minutes
5+
STALE_EXEMPTIONS = ["imports"]
56

67
Thread.new do
78
loop do
89
begin
9-
`ps -e -o pid,command | grep [r]esque`.split("\n").each do |line|
10+
lines = `ps -e -o pid,command | grep [r]esque`.split("\n")
11+
lines.each do |line|
1012
parts = line.split(' ')
1113
next if parts[-2] != "at"
1214
started = parts[-1].to_i
1315
elapsed = Time.now - Time.at(started)
1416

1517
if elapsed >= WORKER_TIMEOUT
18+
parent = lines.detect { |line| line.split(" ").first == parts[3] }
19+
queue = parent.split(" ")[3]
20+
next if STALE_EXEMPTIONS.include?(queue)
1621
::Process.kill('USR1', parts[0].to_i)
1722
end
1823
end

lib/resque.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ def coder
6565
# create a new one.
6666
def redis
6767
return @redis if @redis
68-
self.redis = Redis.respond_to?(:connect) ? Redis.connect : "localhost:6379"
68+
self.redis = Redis.respond_to?(:connect) ? Redis.connect(:thread_safe => true) : "localhost:6379"
6969
self.redis
7070
end
7171

@@ -139,7 +139,7 @@ def to_s
139139
# Pushes a job onto a queue. Queue name should be a string and the
140140
# item should be any JSON-able Ruby object.
141141
#
142-
# Resque works generally expect the `item` to be a hash with the following
142+
# Resque workers generally expect the `item` to be a hash with the following
143143
# keys:
144144
#
145145
# class - The String name of the job to run.

lib/resque/failure/redis.rb

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ module Failure
55
class Redis < Base
66
def save
77
data = {
8-
:failed_at => Time.now.strftime("%Y/%m/%d %H:%M:%S %Z"),
8+
:failed_at => Time.now.rfc2822,
99
:payload => payload,
1010
:exception => exception.class.to_s,
1111
:error => UTF8Util.clean(exception.to_s),
@@ -31,7 +31,7 @@ def self.clear
3131

3232
def self.requeue(index)
3333
item = all(index)
34-
item['retried_at'] = Time.now.strftime("%Y/%m/%d %H:%M:%S")
34+
item['retried_at'] = Time.now.rfc2822
3535
Resque.redis.lset(:failed, index, Resque.encode(item))
3636
Job.create(item['queue'], item['payload']['class'], *item['payload']['args'])
3737
end
@@ -43,8 +43,12 @@ def self.remove(index)
4343
end
4444

4545
def filter_backtrace(backtrace)
46-
index = backtrace.index { |item| item.include?('/lib/resque/job.rb') }
47-
backtrace.first(index.to_i)
46+
index = backtrace.index { |item| item.include?('/lib/resque/job.rb') }.to_i
47+
if index == 0
48+
backtrace
49+
else
50+
backtrace.first(index.to_i)
51+
end
4852
end
4953
end
5054
end

lib/resque/job.rb

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ def perform
111111

112112
begin
113113
# Execute before_perform hook. Abort the job gracefully if
114-
# Resque::DontPerform is raised.
114+
# Resque::Job::DontPerform is raised.
115115
begin
116116
before_hooks.each do |hook|
117117
job.send(hook, *job_args)
@@ -166,6 +166,13 @@ def payload_class
166166
@payload_class ||= constantize(@payload['class'])
167167
end
168168

169+
# returns true if payload_class does not raise NameError
170+
def has_payload_class?
171+
payload_class != Object
172+
rescue NameError
173+
false
174+
end
175+
169176
# Returns an array of args represented in this job's payload.
170177
def args
171178
@payload['args']
@@ -174,7 +181,7 @@ def args
174181
# Given an exception object, hands off the needed parameters to
175182
# the Failure module.
176183
def fail(exception)
177-
run_failure_hooks(exception)
184+
run_failure_hooks(exception) if has_payload_class?
178185
Failure.create \
179186
:payload => payload,
180187
:exception => exception,

lib/resque/multi_queue.rb

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,15 @@ def pop(non_block = false)
4646
end
4747
else
4848
queue_names = @queues.map {|queue| queue.redis_name }
49-
synchronize do
50-
value = @redis.blpop(*(queue_names + [1])) until value
51-
queue_name, payload = value
52-
queue = @queue_hash[queue_name]
53-
[queue, queue.decode(payload)]
49+
if queue_names.any?
50+
synchronize do
51+
value = @redis.blpop(*(queue_names + [1])) until value
52+
queue_name, payload = value
53+
queue = @queue_hash["#{@redis.namespace}:#{queue_name}"]
54+
[queue, queue.decode(payload)]
55+
end
56+
else
57+
Kernel.sleep # forever
5458
end
5559
end
5660
end
@@ -61,12 +65,17 @@ def pop(non_block = false)
6165
# the timeout expires.
6266
def poll(timeout)
6367
queue_names = @queues.map {|queue| queue.redis_name }
64-
queue_name, payload = @redis.blpop(*(queue_names + [timeout]))
65-
return unless payload
68+
if queue_names.any?
69+
queue_name, payload = @redis.blpop(*(queue_names + [timeout]))
70+
return unless payload
6671

67-
synchronize do
68-
queue = @queue_hash[queue_name]
69-
[queue, queue.decode(payload)]
72+
synchronize do
73+
queue = @queue_hash["#{@redis.namespace}:#{queue_name}"]
74+
[queue, queue.decode(payload)]
75+
end
76+
else
77+
Kernel.sleep(timeout)
78+
nil
7079
end
7180
end
7281
end

lib/resque/server.rb

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,7 @@ class Server < Sinatra::Base
1414

1515
set :views, "#{dir}/server/views"
1616

17-
if respond_to? :public_folder
18-
set :public_folder, "#{dir}/server/public"
19-
else
20-
set :public, "#{dir}/server/public"
21-
end
17+
set :public_folder, "#{dir}/server/public"
2218

2319
set :static, true
2420

@@ -30,6 +26,10 @@ def current_section
3026
url_path request.path_info.sub('/','').split('/')[0].downcase
3127
end
3228

29+
def current_subtab
30+
url_path request.path_info.sub('/','').split('/')[0, 2].join('/').downcase
31+
end
32+
3333
def current_page
3434
url_path request.path_info.sub('/','')
3535
end
@@ -44,7 +44,7 @@ def path_prefix
4444
end
4545

4646
def class_if_current(path = '')
47-
'class="current"' if current_page[0, path.size] == path
47+
'class="current"' if [current_section, current_subtab].include?(path)
4848
end
4949

5050
def tab(name)

lib/resque/server/public/ranger.js

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,9 @@ $(function() {
3535
return false
3636
})
3737

38-
$('a[rel=poll]').click(function() {
39-
var href = $(this).attr('href')
40-
$(this).parent().text('Starting...')
38+
var poll_start = function(el) {
39+
var href = el.attr('href')
40+
el.parent().text('Starting...')
4141
$("#main").addClass('polling')
4242

4343
setInterval(function() {
@@ -47,8 +47,14 @@ $(function() {
4747
}})
4848
}, poll_interval * 1000)
4949

50+
location.hash = '#poll'
51+
5052
return false
51-
})
53+
};
54+
55+
if (location.hash == '#poll') poll_start($('a[rel=poll]'))
56+
57+
$('a[rel=poll]').click(function() { return poll_start($(this)) })
5258

5359
$('ul.failed li').hover(function() {
5460
$(this).addClass('hover');
@@ -69,5 +75,11 @@ $(function() {
6975
return false;
7076
})
7177

78+
$('#clear-failed-jobs').click(function(){
79+
return confirm('Are you sure you want to clear ALL failed jobs?');
80+
})
7281

73-
})
82+
$('#retry-failed-jobs').click(function(){
83+
return confirm('Are you sure you want to retry ALL failed jobs?');
84+
})
85+
})

lib/resque/server/public/style.css

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ body { padding:0; margin:0; }
7474
#main ul.failed li dl dd .controls { display:none; float:right; }
7575
#main ul.failed li.hover dl dd .controls { display:block; }
7676
#main ul.failed li dl dd code, #main ul.failed li dl dd pre { font-family:Monaco, "Courier New", monospace; font-size:90%; white-space: pre-wrap;}
77-
#main ul.failed li dl dd.error a {font-family:Monaco, "Courier New", monospace; font-size:90%; }
77+
#main ul.failed li dl dd.error a {font-family:Monaco, "Courier New", monospace; font-size:90%; white-space: pre }
7878
#main ul.failed li dl dd.error pre { margin-top:3px; line-height:1.3;}
7979

8080
#main p.pagination { background:#efefef; padding:10px; overflow:hidden;}

0 commit comments

Comments
 (0)