tresque 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/Gemfile +4 -0
- data/MIT-LICENSE +20 -0
- data/README.md +186 -0
- data/Rakefile +1 -0
- data/lib/tresque.rb +24 -0
- data/lib/tresque/delay.rb +115 -0
- data/lib/tresque/delay_execution_worker.rb +58 -0
- data/lib/tresque/queue_lock.rb +70 -0
- data/lib/tresque/registry.rb +94 -0
- data/lib/tresque/resque_spec/ext.rb +92 -0
- data/lib/tresque/resque_spec/helpers.rb +25 -0
- data/lib/tresque/resque_spec/matchers.rb +318 -0
- data/lib/tresque/resque_spec/resque_spec.rb +201 -0
- data/lib/tresque/resque_spec/scheduler.rb +93 -0
- data/lib/tresque/spec.rb +2 -0
- data/lib/tresque/spec/delay.rb +27 -0
- data/lib/tresque/util.rb +16 -0
- data/lib/tresque/version.rb +3 -0
- data/lib/tresque/worker.rb +228 -0
- data/lib/tresque/worker_lock.rb +53 -0
- data/tresque.gemspec +30 -0
- metadata +141 -0
@@ -0,0 +1,201 @@
|
|
1
|
+
require 'tresque/resque_spec/ext'
|
2
|
+
require 'tresque/resque_spec/helpers'
|
3
|
+
require 'tresque/resque_spec/matchers'
|
4
|
+
|
5
|
+
module ResqueSpec
|
6
|
+
|
7
|
+
# methods to be made accessible for every spec
|
8
|
+
module BaseMethods
|
9
|
+
|
10
|
+
def run_resque_workers(options = {})
|
11
|
+
quantity = options.fetch(:quantity, 1)
|
12
|
+
|
13
|
+
quantity.times do
|
14
|
+
ResqueSpec.perform_all!
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
include ::Resque::Helpers
|
22
|
+
extend self
|
23
|
+
|
24
|
+
attr_accessor :inline
|
25
|
+
attr_accessor :disable_ext
|
26
|
+
|
27
|
+
def dequeue(queue_name, klass, *args)
|
28
|
+
queue_by_name(queue_name).delete_if do |job|
|
29
|
+
job[:class] == klass.to_s && args.empty? || job[:args] == args
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def enqueue(queue_name, klass, *args)
|
34
|
+
perform_or_store(queue_name, :class => klass.to_s, :args => args)
|
35
|
+
end
|
36
|
+
|
37
|
+
def perform_next(queue_name)
|
38
|
+
perform(queue_name, shift_queue(queue_name))
|
39
|
+
end
|
40
|
+
|
41
|
+
def perform_all(queue_name)
|
42
|
+
while job = shift_queue(queue_name)
|
43
|
+
perform(queue_name, job)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def shift_queue(queue_name)
|
48
|
+
# pass scheduled ones
|
49
|
+
array = queue_by_name(queue_name) || []
|
50
|
+
index = nil
|
51
|
+
array.each_with_index do |hash, i|
|
52
|
+
if hash[:time].to_i <= Time.now.to_i
|
53
|
+
index = i
|
54
|
+
break
|
55
|
+
end
|
56
|
+
end
|
57
|
+
return nil unless index
|
58
|
+
array.delete_at(index)
|
59
|
+
end
|
60
|
+
|
61
|
+
def pop(queue_name)
|
62
|
+
return unless payload = shift_queue(queue_name)
|
63
|
+
new_job(queue_name, payload)
|
64
|
+
end
|
65
|
+
|
66
|
+
def queue_by_name(name)
|
67
|
+
queues[name.to_s]
|
68
|
+
end
|
69
|
+
|
70
|
+
def queue_for(klass)
|
71
|
+
queue_by_name(queue_name(klass))
|
72
|
+
end
|
73
|
+
|
74
|
+
def peek(queue_name, start = 0, count = 1)
|
75
|
+
queue_by_name(queue_name).slice(start, count)
|
76
|
+
end
|
77
|
+
|
78
|
+
def queue_name(klass)
|
79
|
+
if klass.is_a?(String)
|
80
|
+
klass = Kernel.const_get(klass) rescue nil
|
81
|
+
end
|
82
|
+
|
83
|
+
name_from_instance_var(klass) or
|
84
|
+
name_from_queue_accessor(klass) or
|
85
|
+
raise ::Resque::NoQueueError.new("Jobs must be placed onto a queue.")
|
86
|
+
end
|
87
|
+
|
88
|
+
def queues
|
89
|
+
@queues ||= Hash.new {|h,k| h[k] = []}
|
90
|
+
end
|
91
|
+
|
92
|
+
def delete_all(queue_name)
|
93
|
+
queue = "queue:#{queue_name}"
|
94
|
+
Resque.redis.del(queue)
|
95
|
+
reset!
|
96
|
+
end
|
97
|
+
|
98
|
+
def perform_all!
|
99
|
+
::TResque::Registry.queues.each do |queue_name|
|
100
|
+
ResqueSpec.perform_all(queue_name)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
# Check if we have queued a delayed worker for `klass` with `*args`
|
105
|
+
# Very slow, checks every `delayed` key
|
106
|
+
def delayed?(klass, *args)
|
107
|
+
klass = klass.to_s unless klass.is_a? String
|
108
|
+
[*Resque.redis.keys("delayed:*")].each do |key|
|
109
|
+
[*Resque.redis.lrange(key, 0, -1)].each do |item|
|
110
|
+
parsed_item = JSON.parse(item)
|
111
|
+
return true if parsed_item['class'] == klass && parsed_item['args'] == [*args]
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
false
|
116
|
+
end
|
117
|
+
|
118
|
+
# Get back the key of the delayed worker if it exists
|
119
|
+
def delayed_key(klass, *args)
|
120
|
+
klass = klass.to_s unless klass.is_a? String
|
121
|
+
[*Resque.redis.keys("delayed:*")].each do |key|
|
122
|
+
[*Resque.redis.lrange(key, 0, -1)].each do |item|
|
123
|
+
parsed_item = JSON.parse(item)
|
124
|
+
return key if parsed_item['class'] == klass && parsed_item['args'] == [*args]
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
nil
|
129
|
+
end
|
130
|
+
|
131
|
+
# check if the worker has a lock with the provided args
|
132
|
+
def locked?(klass, *args)
|
133
|
+
klass = klass.to_s unless klass.is_a? String
|
134
|
+
|
135
|
+
key = "lock:#{klass}-#{[*args].join('-')}"
|
136
|
+
Resque.redis.keys(key).present?
|
137
|
+
end
|
138
|
+
|
139
|
+
def clear_locked!
|
140
|
+
[*Resque.redis.keys("lock:*")].each do |key|
|
141
|
+
Resque.redis.del(key)
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
def clear_all!
|
146
|
+
[*Resque.redis.keys].each do |key|
|
147
|
+
Resque.redis.del(key)
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
def reset!
|
152
|
+
clear_all!
|
153
|
+
queues.clear
|
154
|
+
self.inline = false
|
155
|
+
end
|
156
|
+
|
157
|
+
private
|
158
|
+
|
159
|
+
def name_from_instance_var(klass)
|
160
|
+
klass.instance_variable_get(:@queue)
|
161
|
+
end
|
162
|
+
|
163
|
+
def name_from_queue_accessor(klass)
|
164
|
+
klass.respond_to?(:queue) and klass.queue
|
165
|
+
end
|
166
|
+
|
167
|
+
def new_job(queue_name, payload)
|
168
|
+
Resque::Job.new(queue_name, payload_with_string_keys(payload))
|
169
|
+
end
|
170
|
+
|
171
|
+
def perform(queue_name, payload)
|
172
|
+
prev = ENV['QUEUE']
|
173
|
+
ENV['QUEUE'] = queue_name
|
174
|
+
new_job(queue_name, payload).perform
|
175
|
+
ensure
|
176
|
+
ENV['QUEUE'] = prev
|
177
|
+
end
|
178
|
+
|
179
|
+
def perform_or_store(queue_name, payload)
|
180
|
+
if inline
|
181
|
+
perform(queue_name, payload)
|
182
|
+
else
|
183
|
+
store(queue_name, payload)
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
def store(queue_name, payload)
|
188
|
+
queue_by_name(queue_name) << payload
|
189
|
+
end
|
190
|
+
|
191
|
+
def payload_with_string_keys(payload)
|
192
|
+
{
|
193
|
+
'class' => payload[:class],
|
194
|
+
'args' => decode(encode(payload[:args])),
|
195
|
+
'stored_at' => payload[:stored_at]
|
196
|
+
}
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
config = RSpec.configuration
|
201
|
+
config.include ::ResqueSpec::Helpers
|
@@ -0,0 +1,93 @@
|
|
1
|
+
require_relative 'resque_spec'
|
2
|
+
|
3
|
+
module ResqueSpec
|
4
|
+
module SchedulerExt
|
5
|
+
def self.extended(klass)
|
6
|
+
if klass.respond_to? :enqueue_at
|
7
|
+
klass.instance_eval do
|
8
|
+
alias :enqueue_at_without_resque_spec :enqueue_at
|
9
|
+
alias :enqueue_in_without_resque_spec :enqueue_in
|
10
|
+
alias :remove_delayed_without_resque_spec :remove_delayed
|
11
|
+
end
|
12
|
+
end
|
13
|
+
klass.extend(ResqueSpec::SchedulerExtMethods)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
module SchedulerExtMethods
|
18
|
+
def enqueue_at(time, klass, *args)
|
19
|
+
return enqueue_at_without_resque_spec(time, klass, *args) if ResqueSpec.disable_ext && respond_to?(:enqueue_at_without_resque_spec)
|
20
|
+
|
21
|
+
ResqueSpec.enqueue_at(time, klass, *args)
|
22
|
+
end
|
23
|
+
|
24
|
+
def enqueue_at_with_queue(queue, time, klass, *args)
|
25
|
+
return enqueue_at_with_queue_without_resque_spec(time, klass, *args) if ResqueSpec.disable_ext && respond_to?(:enqueue_at_with_queue_without_resque_spec)
|
26
|
+
|
27
|
+
ResqueSpec.enqueue_at_with_queue(queue, time, klass, *args)
|
28
|
+
end
|
29
|
+
|
30
|
+
def enqueue_in(time, klass, *args)
|
31
|
+
return enqueue_in_without_resque_spec(time, klass, *args) if ResqueSpec.disable_ext && respond_to?(:enqueue_in_without_resque_spec)
|
32
|
+
|
33
|
+
ResqueSpec.enqueue_in(time, klass, *args)
|
34
|
+
end
|
35
|
+
|
36
|
+
def enqueue_in_with_queue(queue, time, klass, *args)
|
37
|
+
return enqueue_in_with_queue_without_resque_spec(time, klass, *args) if ResqueSpec.disable_ext && respond_to?(:enqueue_in_with_queue_without_resque_spec)
|
38
|
+
|
39
|
+
ResqueSpec.enqueue_in_with_queue(queue, time, klass, *args)
|
40
|
+
end
|
41
|
+
|
42
|
+
def remove_delayed(klass, *args)
|
43
|
+
return remove_delayed_without_resque_spec(klass, *args) if ResqueSpec.disable_ext && respond_to?(:remove_delayed_without_resque_spec)
|
44
|
+
|
45
|
+
ResqueSpec.remove_delayed(klass, *args)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def enqueue_at(time, klass, *args)
|
50
|
+
enqueue_at_with_queue(schedule_queue_name(klass), time, klass, *args)
|
51
|
+
end
|
52
|
+
|
53
|
+
def enqueue_at_with_queue(queue, time, klass, *args)
|
54
|
+
is_time?(time)
|
55
|
+
perform_or_store(queue, :class => klass.to_s, :time => time, :stored_at => Time.now, :args => args)
|
56
|
+
end
|
57
|
+
|
58
|
+
def enqueue_in(time, klass, *args)
|
59
|
+
enqueue_at(Time.now + time, klass, *args)
|
60
|
+
end
|
61
|
+
|
62
|
+
def enqueue_in_with_queue(queue, time, klass, *args)
|
63
|
+
enqueue_at_with_queue(queue, Time.now + time, klass, *args)
|
64
|
+
end
|
65
|
+
|
66
|
+
def remove_delayed(klass, *args)
|
67
|
+
sched_queue = queue_by_name(schedule_queue_name(klass))
|
68
|
+
count_before_remove = sched_queue.length
|
69
|
+
sched_queue.delete_if do |job|
|
70
|
+
job[:class] == klass.to_s && job[:args] == args
|
71
|
+
end
|
72
|
+
# Return number of removed items to match Resque Scheduler behaviour
|
73
|
+
count_before_remove - sched_queue.length
|
74
|
+
end
|
75
|
+
|
76
|
+
def schedule_for(klass)
|
77
|
+
queue_by_name(schedule_queue_name(klass))
|
78
|
+
end
|
79
|
+
|
80
|
+
private
|
81
|
+
|
82
|
+
def is_time?(time)
|
83
|
+
time.to_i
|
84
|
+
end
|
85
|
+
|
86
|
+
def schedule_queue_name(klass)
|
87
|
+
# "#{queue_name(klass)}_scheduled"
|
88
|
+
# we use the real one
|
89
|
+
queue_name(klass)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
Resque.extend(ResqueSpec::SchedulerExt)
|
data/lib/tresque/spec.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
module TResque
|
2
|
+
module Spec
|
3
|
+
module Delay
|
4
|
+
|
5
|
+
def delay_object
|
6
|
+
TResque::Delay::InvocationProxy.any_instance
|
7
|
+
end
|
8
|
+
|
9
|
+
def without_delay
|
10
|
+
return yield unless Rails.env.test?
|
11
|
+
|
12
|
+
q = ENV['QUEUE']
|
13
|
+
qs = ENV['QUEUES']
|
14
|
+
|
15
|
+
ENV['QUEUE'] = "v3_default"
|
16
|
+
ENV['QUEUES'] = nil
|
17
|
+
|
18
|
+
yield
|
19
|
+
|
20
|
+
ensure
|
21
|
+
ENV['QUEUE'] = q
|
22
|
+
ENV['QUEUES'] = qs
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
data/lib/tresque/util.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
module TResque
|
2
|
+
module Util
|
3
|
+
extend self
|
4
|
+
|
5
|
+
def normalize(val)
|
6
|
+
val.to_s.gsub(/\W/, "_").downcase
|
7
|
+
end
|
8
|
+
|
9
|
+
def calculate_namespace_from_class(klass)
|
10
|
+
klass = klass.class unless klass.is_a?(Class)
|
11
|
+
pieces = klass.name.to_s.split("::")
|
12
|
+
return "worker" if pieces.size < 2
|
13
|
+
pieces.first.underscore
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,228 @@
|
|
1
|
+
require 'resque-retry'
|
2
|
+
require 'digest/sha1'
|
3
|
+
|
4
|
+
module TResque
|
5
|
+
module Worker
|
6
|
+
extend ::ActiveSupport::Concern
|
7
|
+
|
8
|
+
mattr_accessor :skip_check_queues
|
9
|
+
|
10
|
+
included do
|
11
|
+
extend ::Resque::Plugins::ExponentialBackoff
|
12
|
+
TResque::Registry.worker(self)
|
13
|
+
end
|
14
|
+
|
15
|
+
module ClassMethods
|
16
|
+
def queue(name=nil)
|
17
|
+
return @requeue_in_queue if !name && @requeue_in_queue
|
18
|
+
return @queue if !name && @queue
|
19
|
+
name ||= :default
|
20
|
+
full_queue("#{app_key}_#{name}")
|
21
|
+
end
|
22
|
+
|
23
|
+
def full_queue(name)
|
24
|
+
@queue = name.to_s
|
25
|
+
end
|
26
|
+
|
27
|
+
def application(app_key)
|
28
|
+
@app_key = Util.normalize(app_key)
|
29
|
+
end
|
30
|
+
|
31
|
+
def app_key
|
32
|
+
return @app_key if @app_key
|
33
|
+
@app_key = Util.calculate_namespace_from_class(self)
|
34
|
+
end
|
35
|
+
|
36
|
+
def enqueue(options = {})
|
37
|
+
options = options.with_indifferent_access
|
38
|
+
|
39
|
+
options[:locale] ||= I18n.locale.to_s
|
40
|
+
options[:tz] ||= Time.zone.name
|
41
|
+
|
42
|
+
run_at = options.delete(:run_at)
|
43
|
+
if options[:full_queue]
|
44
|
+
queue_name = options[:full_queue]
|
45
|
+
elsif options[:queue] || options[:queue_namespace]
|
46
|
+
namespace = options[:queue_namespace] || self.app_key
|
47
|
+
queue = options[:queue] || "default"
|
48
|
+
queue_name = "#{namespace}_#{queue}"
|
49
|
+
else
|
50
|
+
queue_name = self.queue
|
51
|
+
end
|
52
|
+
|
53
|
+
if queue_name == "t_resque_default"
|
54
|
+
message = "QUEUE_ERROR (#{self.class.name}): #{queue_name} will not be worked!"
|
55
|
+
Rails.logger.error(message)
|
56
|
+
puts message if Rails.env.test?
|
57
|
+
end
|
58
|
+
|
59
|
+
if !TResque::Worker.skip_check_queues && !TResque::Registry.queues.include?(queue_name)
|
60
|
+
message = "QUEUE_ERROR (#{self.class.name}): #{queue_name} will not be worked!"
|
61
|
+
Rails.logger.error(message)
|
62
|
+
puts message if Rails.env.test?
|
63
|
+
end
|
64
|
+
|
65
|
+
options[:full_queue] = queue_name
|
66
|
+
if run_at
|
67
|
+
Resque.enqueue_at_with_queue(queue_name, run_at, self, options)
|
68
|
+
else
|
69
|
+
Resque.enqueue_to(queue_name, self, options)
|
70
|
+
end
|
71
|
+
|
72
|
+
# too many events
|
73
|
+
# QueueBus.publish_log(:worker_enqueued, {
|
74
|
+
# options: options,
|
75
|
+
# queue_name: queue_name,
|
76
|
+
# worker_name: self.name.to_s,
|
77
|
+
# run_at: run_at.to_i
|
78
|
+
# }) unless Rails.env.test?
|
79
|
+
|
80
|
+
options
|
81
|
+
end
|
82
|
+
|
83
|
+
def perform(options)
|
84
|
+
Waistband.clear_logs if Waistband.config.logging
|
85
|
+
|
86
|
+
@previous_locale, @previous_zone = I18n.locale, Time.zone
|
87
|
+
|
88
|
+
options = options.with_indifferent_access
|
89
|
+
obj = self.new(options.except(:locale, :tz, :bus_locale, :bus_timezone))
|
90
|
+
|
91
|
+
locale = obj.respond_to?(:calculate_locale, true) ? obj.send(:calculate_locale) : nil
|
92
|
+
locale ||= options[:locale]
|
93
|
+
locale ||= options[:bus_locale]
|
94
|
+
locale ||= I18n.locale if Rails.env.production? # don't crash in production, use default
|
95
|
+
|
96
|
+
zone = obj.respond_to?(:calculate_timezone, true) ? obj.send(:calculate_timezone) : nil
|
97
|
+
zone ||= options[:tz]
|
98
|
+
zone ||= options[:bus_timezone]
|
99
|
+
|
100
|
+
I18n.locale = locale
|
101
|
+
Time.zone = zone
|
102
|
+
|
103
|
+
# too many events
|
104
|
+
# QueueBus.publish_log(:worker_perform, {
|
105
|
+
# options: options,
|
106
|
+
# worker_name: self.name.to_s,
|
107
|
+
# locale: locale,
|
108
|
+
# time_zone: zone
|
109
|
+
# }) unless Rails.env.test?
|
110
|
+
|
111
|
+
obj.worker_perform
|
112
|
+
rescue Resque::Job::DontPerform
|
113
|
+
# it's cool
|
114
|
+
ensure
|
115
|
+
# write waistband logs
|
116
|
+
Waistband.write_logs(nil) if Waistband.config.logging
|
117
|
+
# reset
|
118
|
+
I18n.locale, Time.zone = @previous_locale, @previous_zone
|
119
|
+
end
|
120
|
+
|
121
|
+
def inputs(*args)
|
122
|
+
args.each do |name|
|
123
|
+
define_method name do
|
124
|
+
enqueued_options[name]
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
alias_method :input, :inputs
|
129
|
+
|
130
|
+
def turn_retry_off
|
131
|
+
@retry_limit = 0
|
132
|
+
end
|
133
|
+
|
134
|
+
def lock_namespace(val)
|
135
|
+
@lock_namespace = val.to_s
|
136
|
+
end
|
137
|
+
|
138
|
+
def worker_lock(*args)
|
139
|
+
raise ("worker_lock: what should i lock on?") if args.size == 0
|
140
|
+
extend ::TResque::WorkerLock
|
141
|
+
@worker_lock_attributes = args.collect(&:to_s)
|
142
|
+
end
|
143
|
+
|
144
|
+
def queue_lock(*args)
|
145
|
+
raise ("queue_lock: what should i lock on?") if args.size == 0
|
146
|
+
extend ::TResque::QueueLock
|
147
|
+
@queue_lock_attributes = args.collect(&:to_s)
|
148
|
+
end
|
149
|
+
|
150
|
+
def get_lock_namespace(options)
|
151
|
+
@lock_namespace ||= self.name
|
152
|
+
end
|
153
|
+
|
154
|
+
def get_queue_lock_attributes(options)
|
155
|
+
@queue_lock_attributes ||= []
|
156
|
+
end
|
157
|
+
|
158
|
+
def get_worker_lock_attributes(options)
|
159
|
+
@worker_lock_attributes ||= []
|
160
|
+
end
|
161
|
+
|
162
|
+
def queue_lock_key(options)
|
163
|
+
options_lock_key(options, get_queue_lock_attributes(options))
|
164
|
+
end
|
165
|
+
|
166
|
+
def worker_lock_key(options)
|
167
|
+
options_lock_key(options, get_worker_lock_attributes(options))
|
168
|
+
end
|
169
|
+
|
170
|
+
def options_lock_key(options, keys)
|
171
|
+
return nil unless keys # not actually locking
|
172
|
+
|
173
|
+
keys = ["all"] if keys.size == 0
|
174
|
+
keys = options.keys if keys.size == 1 && keys.first == "all"
|
175
|
+
keys.sort!
|
176
|
+
|
177
|
+
vals = [get_lock_namespace(options)]
|
178
|
+
keys.each do |key|
|
179
|
+
vals << key
|
180
|
+
vals << options[key].to_s
|
181
|
+
end
|
182
|
+
Digest::SHA1.hexdigest(vals.join("-"))
|
183
|
+
end
|
184
|
+
|
185
|
+
# make sure we put it back in the same queue
|
186
|
+
# @failure_hooks_already_ran on https://github.com/defunkt/resque/tree/1-x-stable
|
187
|
+
# to prevent running twice
|
188
|
+
def on_failure_aaa(exception, *args)
|
189
|
+
# note: sorted alphabetically
|
190
|
+
# queue needs to be set for rety to work (know what queue in Requeue.class_to_queue)
|
191
|
+
@requeue_in_queue = args[0]["full_queue"]
|
192
|
+
end
|
193
|
+
|
194
|
+
def on_failure_zzz(exception, *args)
|
195
|
+
# note: sorted alphabetically
|
196
|
+
@requeue_in_queue = nil
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
attr_reader :enqueued_options
|
201
|
+
def initialize(options = {})
|
202
|
+
@enqueued_options = options.with_indifferent_access
|
203
|
+
end
|
204
|
+
|
205
|
+
def worker_perform
|
206
|
+
to_call = self.enqueued_options[:action] || :work
|
207
|
+
send(to_call)
|
208
|
+
end
|
209
|
+
|
210
|
+
def requeue_delay_seconds
|
211
|
+
1
|
212
|
+
end
|
213
|
+
|
214
|
+
def requeue
|
215
|
+
self.enqueued_options["run_at"] = nil
|
216
|
+
delay = self.requeue_delay_seconds
|
217
|
+
if delay > 0
|
218
|
+
self.enqueued_options["run_at"] = delay.seconds.from_now
|
219
|
+
end
|
220
|
+
self.class.enqueue(self.enqueued_options)
|
221
|
+
end
|
222
|
+
|
223
|
+
def requeue!
|
224
|
+
requeue
|
225
|
+
raise Resque::Job::DontPerform
|
226
|
+
end
|
227
|
+
end
|
228
|
+
end
|