resque 1.26.pre.0 → 1.26.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.
- checksums.yaml +7 -0
- data/HISTORY.md +29 -16
- data/README.markdown +60 -6
- data/Rakefile +4 -17
- data/bin/resque-web +4 -0
- data/lib/resque.rb +116 -16
- data/lib/resque/errors.rb +1 -0
- data/lib/resque/failure.rb +11 -5
- data/lib/resque/failure/multiple.rb +6 -1
- data/lib/resque/failure/redis.rb +13 -4
- data/lib/resque/failure/redis_multi_queue.rb +14 -6
- data/lib/resque/helpers.rb +5 -64
- data/lib/resque/job.rb +25 -79
- data/lib/resque/logging.rb +1 -1
- data/lib/resque/plugin.rb +22 -10
- data/lib/resque/server.rb +35 -7
- data/lib/resque/server/helpers.rb +1 -1
- data/lib/resque/server/views/failed.erb +1 -1
- data/lib/resque/server/views/failed_job.erb +3 -3
- data/lib/resque/server/views/failed_queues_overview.erb +3 -3
- data/lib/resque/server/views/workers.erb +2 -0
- data/lib/resque/server/views/working.erb +4 -5
- data/lib/resque/tasks.rb +7 -25
- data/lib/resque/vendor/utf8_util/utf8_util_19.rb +1 -0
- data/lib/resque/version.rb +1 -1
- data/lib/resque/worker.rb +225 -116
- metadata +68 -90
- data/test/airbrake_test.rb +0 -27
- data/test/dump.rdb +0 -0
- data/test/failure_base_test.rb +0 -15
- data/test/job_hooks_test.rb +0 -464
- data/test/job_plugins_test.rb +0 -230
- data/test/logging_test.rb +0 -24
- 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_hook_test.rb +0 -165
- data/test/resque_test.rb +0 -278
- data/test/test_helper.rb +0 -198
- data/test/worker_test.rb +0 -1015
@@ -27,6 +27,11 @@ module Resque
|
|
27
27
|
classes.first.count(*args)
|
28
28
|
end
|
29
29
|
|
30
|
+
# Returns an array of all available failure queues
|
31
|
+
def self.queues
|
32
|
+
classes.first.queues
|
33
|
+
end
|
34
|
+
|
30
35
|
# Returns a paginated array of failure objects.
|
31
36
|
def self.all(*args)
|
32
37
|
classes.first.all(*args)
|
@@ -51,7 +56,7 @@ module Resque
|
|
51
56
|
classes.first.requeue(*args)
|
52
57
|
end
|
53
58
|
|
54
|
-
def self.remove(index)
|
59
|
+
def self.remove(index, queue)
|
55
60
|
classes.each { |klass| klass.remove(index) }
|
56
61
|
end
|
57
62
|
end
|
data/lib/resque/failure/redis.rb
CHANGED
@@ -39,7 +39,7 @@ module Resque
|
|
39
39
|
end
|
40
40
|
|
41
41
|
def self.each(offset = 0, limit = self.count, queue = :failed, class_name = nil, order = 'desc')
|
42
|
-
all_items = Array(all(offset, limit, queue))
|
42
|
+
all_items = limit == 1 ? [all(offset,limit,queue)] : Array(all(offset, limit, queue))
|
43
43
|
reversed = false
|
44
44
|
if order.eql? 'desc'
|
45
45
|
all_items.reverse!
|
@@ -48,7 +48,7 @@ module Resque
|
|
48
48
|
all_items.each_with_index do |item, i|
|
49
49
|
if !class_name || (item['payload'] && item['payload']['class'] == class_name)
|
50
50
|
if reversed
|
51
|
-
id = (all_items.length - 1)
|
51
|
+
id = (all_items.length - 1) + (offset - i)
|
52
52
|
else
|
53
53
|
id = offset + i
|
54
54
|
end
|
@@ -62,14 +62,16 @@ module Resque
|
|
62
62
|
Resque.redis.del(:failed)
|
63
63
|
end
|
64
64
|
|
65
|
-
def self.requeue(id)
|
65
|
+
def self.requeue(id, queue = nil)
|
66
|
+
check_queue(queue)
|
66
67
|
item = all(id)
|
67
68
|
item['retried_at'] = Time.now.strftime("%Y/%m/%d %H:%M:%S")
|
68
69
|
Resque.redis.lset(:failed, id, Resque.encode(item))
|
69
70
|
Job.create(item['queue'], item['payload']['class'], *item['payload']['args'])
|
70
71
|
end
|
71
72
|
|
72
|
-
def self.remove(id)
|
73
|
+
def self.remove(id, queue = nil)
|
74
|
+
check_queue(queue)
|
73
75
|
sentinel = ""
|
74
76
|
Resque.redis.lset(:failed, id, sentinel)
|
75
77
|
Resque.redis.lrem(:failed, 1, sentinel)
|
@@ -83,6 +85,12 @@ module Resque
|
|
83
85
|
end
|
84
86
|
end
|
85
87
|
|
88
|
+
def self.requeue_all
|
89
|
+
count.times do |num|
|
90
|
+
requeue(num)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
86
94
|
def self.remove_queue(queue)
|
87
95
|
i = 0
|
88
96
|
while job = all(i)
|
@@ -103,6 +111,7 @@ module Resque
|
|
103
111
|
index = backtrace.index { |item| item.include?('/lib/resque/job.rb') }
|
104
112
|
backtrace.first(index.to_i)
|
105
113
|
end
|
114
|
+
|
106
115
|
end
|
107
116
|
end
|
108
117
|
end
|
@@ -33,8 +33,8 @@ module Resque
|
|
33
33
|
end
|
34
34
|
end
|
35
35
|
|
36
|
-
def self.all(offset = 0, limit = 1, queue = :failed
|
37
|
-
Resque.list_range(queue, offset, limit
|
36
|
+
def self.all(offset = 0, limit = 1, queue = :failed)
|
37
|
+
Resque.list_range(queue, offset, limit)
|
38
38
|
end
|
39
39
|
|
40
40
|
def self.queues
|
@@ -42,20 +42,24 @@ module Resque
|
|
42
42
|
end
|
43
43
|
|
44
44
|
def self.each(offset = 0, limit = self.count, queue = :failed, class_name = nil, order = 'desc')
|
45
|
-
items = all(offset, limit, queue
|
45
|
+
items = all(offset, limit, queue)
|
46
46
|
items = [items] unless items.is_a? Array
|
47
|
+
reversed = false
|
47
48
|
if order.eql? 'desc'
|
48
49
|
items.reverse!
|
50
|
+
reversed = true
|
49
51
|
end
|
50
52
|
items.each_with_index do |item, i|
|
51
53
|
if !class_name || (item['payload'] && item['payload']['class'] == class_name)
|
52
|
-
|
54
|
+
id = reversed ? (items.length - 1) - (offset + i) : offset + i
|
55
|
+
yield id, item
|
53
56
|
end
|
54
57
|
end
|
55
58
|
end
|
56
59
|
|
57
|
-
def self.clear(queue =
|
58
|
-
|
60
|
+
def self.clear(queue = nil)
|
61
|
+
queues = queue ? Array(queue) : self.queues
|
62
|
+
queues.each { |queue| Resque.redis.del(queue) }
|
59
63
|
end
|
60
64
|
|
61
65
|
def self.requeue(id, queue = :failed)
|
@@ -76,6 +80,10 @@ module Resque
|
|
76
80
|
each(0, count(failure_queue), failure_queue) { |id, _| requeue(id, failure_queue) }
|
77
81
|
end
|
78
82
|
|
83
|
+
def self.requeue_all
|
84
|
+
queues.each { |queue| requeue_queue(Resque::Failure.job_queue_name(queue)) }
|
85
|
+
end
|
86
|
+
|
79
87
|
def self.remove_queue(queue)
|
80
88
|
Resque.redis.del(Resque::Failure.failure_queue_name(queue))
|
81
89
|
end
|
data/lib/resque/helpers.rb
CHANGED
@@ -11,14 +11,6 @@ end
|
|
11
11
|
module Resque
|
12
12
|
# Methods used by various classes in Resque.
|
13
13
|
module Helpers
|
14
|
-
def self.extended(parent_class)
|
15
|
-
warn("Resque::Helpers will be gone with no replacement in Resque 2.0.0.")
|
16
|
-
end
|
17
|
-
|
18
|
-
def self.included(parent_class)
|
19
|
-
warn("Resque::Helpers will be gone with no replacement in Resque 2.0.0.")
|
20
|
-
end
|
21
|
-
|
22
14
|
class DecodeException < StandardError; end
|
23
15
|
|
24
16
|
# Direct access to the Redis instance.
|
@@ -35,73 +27,22 @@ module Resque
|
|
35
27
|
# Given a Ruby object, returns a string suitable for storage in a
|
36
28
|
# queue.
|
37
29
|
def encode(object)
|
38
|
-
|
39
|
-
MultiJson.dump object
|
40
|
-
else
|
41
|
-
MultiJson.encode object
|
42
|
-
end
|
30
|
+
Resque.encode(object)
|
43
31
|
end
|
44
32
|
|
45
33
|
# Given a string, returns a Ruby object.
|
46
34
|
def decode(object)
|
47
|
-
|
48
|
-
|
49
|
-
begin
|
50
|
-
if MultiJson.respond_to?(:dump) && MultiJson.respond_to?(:load)
|
51
|
-
MultiJson.load object
|
52
|
-
else
|
53
|
-
MultiJson.decode object
|
54
|
-
end
|
55
|
-
rescue ::MultiJson::DecodeError => e
|
56
|
-
raise DecodeException, e.message, e.backtrace
|
57
|
-
end
|
35
|
+
Resque.decode(object)
|
58
36
|
end
|
59
37
|
|
60
38
|
# Given a word with dashes, returns a camel cased version of it.
|
61
|
-
#
|
62
|
-
# classify('job-name') # => 'JobName'
|
63
39
|
def classify(dashed_word)
|
64
|
-
|
40
|
+
Resque.classify(dashed_word)
|
65
41
|
end
|
66
42
|
|
67
|
-
# Tries to find a constant with the name specified in the argument string
|
68
|
-
#
|
69
|
-
# constantize("Module") # => Module
|
70
|
-
# constantize("Test::Unit") # => Test::Unit
|
71
|
-
#
|
72
|
-
# The name is assumed to be the one of a top-level constant, no matter
|
73
|
-
# whether it starts with "::" or not. No lexical context is taken into
|
74
|
-
# account:
|
75
|
-
#
|
76
|
-
# C = 'outside'
|
77
|
-
# module M
|
78
|
-
# C = 'inside'
|
79
|
-
# C # => 'inside'
|
80
|
-
# constantize("C") # => 'outside', same as ::C
|
81
|
-
# end
|
82
|
-
#
|
83
|
-
# NameError is raised when the constant is unknown.
|
43
|
+
# Tries to find a constant with the name specified in the argument string
|
84
44
|
def constantize(camel_cased_word)
|
85
|
-
camel_cased_word
|
86
|
-
|
87
|
-
if camel_cased_word.include?('-')
|
88
|
-
camel_cased_word = classify(camel_cased_word)
|
89
|
-
end
|
90
|
-
|
91
|
-
names = camel_cased_word.split('::')
|
92
|
-
names.shift if names.empty? || names.first.empty?
|
93
|
-
|
94
|
-
constant = Object
|
95
|
-
names.each do |name|
|
96
|
-
args = Module.method(:const_get).arity != 1 ? [false] : []
|
97
|
-
|
98
|
-
if constant.const_defined?(name, *args)
|
99
|
-
constant = constant.const_get(name)
|
100
|
-
else
|
101
|
-
constant = constant.const_missing(name)
|
102
|
-
end
|
103
|
-
end
|
104
|
-
constant
|
45
|
+
Resque.constantize(camel_cased_word)
|
105
46
|
end
|
106
47
|
end
|
107
48
|
end
|
data/lib/resque/job.rb
CHANGED
@@ -12,6 +12,8 @@ module Resque
|
|
12
12
|
# klass = Resque::Job.constantize(job.payload['class'])
|
13
13
|
# klass.perform(*job.payload['args'])
|
14
14
|
class Job
|
15
|
+
include Helpers
|
16
|
+
extend Helpers
|
15
17
|
def redis
|
16
18
|
Resque.redis
|
17
19
|
end
|
@@ -23,98 +25,33 @@ module Resque
|
|
23
25
|
# Given a Ruby object, returns a string suitable for storage in a
|
24
26
|
# queue.
|
25
27
|
def encode(object)
|
26
|
-
|
27
|
-
MultiJson.dump object
|
28
|
-
else
|
29
|
-
MultiJson.encode object
|
30
|
-
end
|
28
|
+
Resque.encode(object)
|
31
29
|
end
|
32
30
|
|
33
31
|
# Given a string, returns a Ruby object.
|
34
32
|
def decode(object)
|
35
|
-
|
36
|
-
|
37
|
-
begin
|
38
|
-
if MultiJson.respond_to?(:dump) && MultiJson.respond_to?(:load)
|
39
|
-
MultiJson.load object
|
40
|
-
else
|
41
|
-
MultiJson.decode object
|
42
|
-
end
|
43
|
-
rescue ::MultiJson::DecodeError => e
|
44
|
-
raise DecodeException, e.message, e.backtrace
|
45
|
-
end
|
33
|
+
Resque.decode(object)
|
46
34
|
end
|
47
35
|
|
48
36
|
# Given a Ruby object, returns a string suitable for storage in a
|
49
37
|
# queue.
|
50
38
|
def self.encode(object)
|
51
|
-
|
52
|
-
MultiJson.dump object
|
53
|
-
else
|
54
|
-
MultiJson.encode object
|
55
|
-
end
|
39
|
+
Resque.encode(object)
|
56
40
|
end
|
57
41
|
|
58
42
|
# Given a string, returns a Ruby object.
|
59
43
|
def self.decode(object)
|
60
|
-
|
61
|
-
|
62
|
-
begin
|
63
|
-
if MultiJson.respond_to?(:dump) && MultiJson.respond_to?(:load)
|
64
|
-
MultiJson.load object
|
65
|
-
else
|
66
|
-
MultiJson.decode object
|
67
|
-
end
|
68
|
-
rescue ::MultiJson::DecodeError => e
|
69
|
-
raise DecodeException, e.message, e.backtrace
|
70
|
-
end
|
44
|
+
Resque.decode(object)
|
71
45
|
end
|
72
46
|
|
73
47
|
# Given a word with dashes, returns a camel cased version of it.
|
74
|
-
#
|
75
|
-
# classify('job-name') # => 'JobName'
|
76
48
|
def classify(dashed_word)
|
77
|
-
|
49
|
+
Resque.classify(dashed_word)
|
78
50
|
end
|
79
|
-
|
80
|
-
# Tries to find a constant with the name specified in the argument string:
|
81
|
-
#
|
82
|
-
# constantize("Module") # => Module
|
83
|
-
# constantize("Test::Unit") # => Test::Unit
|
84
|
-
#
|
85
|
-
# The name is assumed to be the one of a top-level constant, no matter
|
86
|
-
# whether it starts with "::" or not. No lexical context is taken into
|
87
|
-
# account:
|
88
|
-
#
|
89
|
-
# C = 'outside'
|
90
|
-
# module M
|
91
|
-
# C = 'inside'
|
92
|
-
# C # => 'inside'
|
93
|
-
# constantize("C") # => 'outside', same as ::C
|
94
|
-
# end
|
95
|
-
#
|
96
|
-
# NameError is raised when the constant is unknown.
|
97
|
-
def constantize(camel_cased_word)
|
98
|
-
camel_cased_word = camel_cased_word.to_s
|
99
|
-
|
100
|
-
if camel_cased_word.include?('-')
|
101
|
-
camel_cased_word = classify(camel_cased_word)
|
102
|
-
end
|
103
|
-
|
104
|
-
names = camel_cased_word.split('::')
|
105
|
-
names.shift if names.empty? || names.first.empty?
|
106
|
-
|
107
|
-
constant = Object
|
108
|
-
names.each do |name|
|
109
|
-
args = Module.method(:const_get).arity != 1 ? [false] : []
|
110
51
|
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
constant = constant.const_missing(name)
|
115
|
-
end
|
116
|
-
end
|
117
|
-
constant
|
52
|
+
# Tries to find a constant with the name specified in the argument string
|
53
|
+
def constantize(camel_cased_word)
|
54
|
+
Resque.constantize(camel_cased_word)
|
118
55
|
end
|
119
56
|
|
120
57
|
# Raise Resque::Job::DontPerform from a before_perform hook to
|
@@ -289,12 +226,17 @@ module Resque
|
|
289
226
|
# Given an exception object, hands off the needed parameters to
|
290
227
|
# the Failure module.
|
291
228
|
def fail(exception)
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
229
|
+
begin
|
230
|
+
run_failure_hooks(exception)
|
231
|
+
rescue Exception => e
|
232
|
+
raise e
|
233
|
+
ensure
|
234
|
+
Failure.create \
|
235
|
+
:payload => payload,
|
236
|
+
:exception => exception,
|
237
|
+
:worker => worker,
|
238
|
+
:queue => queue
|
239
|
+
end
|
298
240
|
end
|
299
241
|
|
300
242
|
# Creates an identical job, essentially placing this job back on
|
@@ -338,6 +280,10 @@ module Resque
|
|
338
280
|
if has_payload_class?
|
339
281
|
failure_hooks.each { |hook| payload_class.send(hook, exception, *job_args) } unless @failure_hooks_ran
|
340
282
|
end
|
283
|
+
rescue Exception => e
|
284
|
+
error_message = "Additional error (#{e.class}: #{e}) occurred in running failure hooks for job #{inspect}\n" \
|
285
|
+
"Original error that caused job failure was #{e.class}: #{exception.class}: #{exception.message}"
|
286
|
+
raise RuntimeError.new(error_message)
|
341
287
|
ensure
|
342
288
|
@failure_hooks_ran = true
|
343
289
|
end
|
data/lib/resque/logging.rb
CHANGED
data/lib/resque/plugin.rb
CHANGED
@@ -11,56 +11,68 @@ module Resque
|
|
11
11
|
hooks = before_hooks(plugin) + around_hooks(plugin) + after_hooks(plugin)
|
12
12
|
|
13
13
|
hooks.each do |hook|
|
14
|
-
if hook
|
14
|
+
if hook.to_s.end_with?("perform")
|
15
15
|
raise LintError, "#{plugin}.#{hook} is not namespaced"
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
19
19
|
failure_hooks(plugin).each do |hook|
|
20
|
-
if hook
|
20
|
+
if hook.to_s.end_with?("failure")
|
21
21
|
raise LintError, "#{plugin}.#{hook} is not namespaced"
|
22
22
|
end
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
26
|
+
@job_methods = {}
|
27
|
+
def job_methods(job)
|
28
|
+
@job_methods[job] ||= job.methods.collect{|m| m.to_s}
|
29
|
+
end
|
30
|
+
|
31
|
+
# Given an object, and a method prefix, returns a list of methods prefixed
|
32
|
+
# with that name (hook names).
|
33
|
+
def get_hook_names(job, hook_method_prefix)
|
34
|
+
methods = (job.respond_to?(:hooks) && job.hooks) || job_methods(job)
|
35
|
+
methods.select{|m| m.start_with?(hook_method_prefix)}.sort
|
36
|
+
end
|
37
|
+
|
26
38
|
# Given an object, returns a list `before_perform` hook names.
|
27
39
|
def before_hooks(job)
|
28
|
-
job
|
40
|
+
get_hook_names(job, 'before_perform')
|
29
41
|
end
|
30
42
|
|
31
43
|
# Given an object, returns a list `around_perform` hook names.
|
32
44
|
def around_hooks(job)
|
33
|
-
job
|
45
|
+
get_hook_names(job, 'around_perform')
|
34
46
|
end
|
35
47
|
|
36
48
|
# Given an object, returns a list `after_perform` hook names.
|
37
49
|
def after_hooks(job)
|
38
|
-
job
|
50
|
+
get_hook_names(job, 'after_perform')
|
39
51
|
end
|
40
52
|
|
41
53
|
# Given an object, returns a list `on_failure` hook names.
|
42
54
|
def failure_hooks(job)
|
43
|
-
job
|
55
|
+
get_hook_names(job, 'on_failure')
|
44
56
|
end
|
45
57
|
|
46
58
|
# Given an object, returns a list `after_enqueue` hook names.
|
47
59
|
def after_enqueue_hooks(job)
|
48
|
-
job
|
60
|
+
get_hook_names(job, 'after_enqueue')
|
49
61
|
end
|
50
62
|
|
51
63
|
# Given an object, returns a list `before_enqueue` hook names.
|
52
64
|
def before_enqueue_hooks(job)
|
53
|
-
job
|
65
|
+
get_hook_names(job, 'before_enqueue')
|
54
66
|
end
|
55
67
|
|
56
68
|
# Given an object, returns a list `after_dequeue` hook names.
|
57
69
|
def after_dequeue_hooks(job)
|
58
|
-
job
|
70
|
+
get_hook_names(job, 'after_dequeue')
|
59
71
|
end
|
60
72
|
|
61
73
|
# Given an object, returns a list `before_dequeue` hook names.
|
62
74
|
def before_dequeue_hooks(job)
|
63
|
-
job
|
75
|
+
get_hook_names(job, 'before_dequeue')
|
64
76
|
end
|
65
77
|
end
|
66
78
|
end
|