resque-scheduler 4.3.1 → 4.6.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-scheduler might be problematic. Click here for more details.
- checksums.yaml +5 -5
- data/.github/dependabot.yml +12 -0
- data/.github/funding.yml +4 -0
- data/.github/workflows/codeql-analysis.yml +59 -0
- data/.github/workflows/rubocop.yml +27 -0
- data/.github/workflows/ruby.yml +66 -0
- data/AUTHORS.md +9 -0
- data/CHANGELOG.md +49 -2
- data/Gemfile +14 -0
- data/README.md +102 -24
- data/Rakefile +2 -5
- data/lib/resque/scheduler/configuration.rb +31 -8
- data/lib/resque/scheduler/delaying_extensions.rb +65 -18
- data/lib/resque/scheduler/env.rb +3 -7
- data/lib/resque/scheduler/lock/resilient.rb +2 -2
- data/lib/resque/scheduler/locking.rb +3 -3
- data/lib/resque/scheduler/scheduling_extensions.rb +4 -3
- data/lib/resque/scheduler/server/views/delayed.erb +4 -4
- data/lib/resque/scheduler/server/views/delayed_timestamp.erb +1 -1
- data/lib/resque/scheduler/server/views/scheduler.erb +2 -2
- data/lib/resque/scheduler/server/views/search.erb +0 -3
- data/lib/resque/scheduler/server/views/search_form.erb +1 -5
- data/lib/resque/scheduler/server.rb +1 -1
- data/lib/resque/scheduler/signal_handling.rb +2 -2
- data/lib/resque/scheduler/util.rb +1 -1
- data/lib/resque/scheduler/version.rb +1 -1
- data/lib/resque/scheduler.rb +27 -15
- data/resque-scheduler.gemspec +14 -8
- metadata +25 -32
@@ -24,7 +24,7 @@ module Resque
|
|
24
24
|
def enqueue_at_with_queue(queue, timestamp, klass, *args)
|
25
25
|
return false unless plugin.run_before_schedule_hooks(klass, *args)
|
26
26
|
|
27
|
-
if Resque.inline? || timestamp.to_i
|
27
|
+
if Resque.inline? || timestamp.to_i <= Time.now.to_i
|
28
28
|
# Just create the job and let resque perform it right away with
|
29
29
|
# inline. If the class is a custom job class, call self#scheduled
|
30
30
|
# on it. This allows you to do things like
|
@@ -33,7 +33,7 @@ module Resque
|
|
33
33
|
if klass.respond_to?(:scheduled)
|
34
34
|
klass.scheduled(queue, klass.to_s, *args)
|
35
35
|
else
|
36
|
-
Resque
|
36
|
+
Resque.enqueue_to(queue, klass, *args)
|
37
37
|
end
|
38
38
|
else
|
39
39
|
delayed_push(timestamp, job_to_hash_with_queue(queue, klass, args))
|
@@ -45,6 +45,9 @@ module Resque
|
|
45
45
|
# Identical to enqueue_at but takes number_of_seconds_from_now
|
46
46
|
# instead of a timestamp.
|
47
47
|
def enqueue_in(number_of_seconds_from_now, klass, *args)
|
48
|
+
unless number_of_seconds_from_now.is_a?(Numeric)
|
49
|
+
raise ArgumentError, 'Please supply a numeric number of seconds'
|
50
|
+
end
|
48
51
|
enqueue_at(Time.now + number_of_seconds_from_now, klass, *args)
|
49
52
|
end
|
50
53
|
|
@@ -53,14 +56,35 @@ module Resque
|
|
53
56
|
# number of seconds has passed.
|
54
57
|
def enqueue_in_with_queue(queue, number_of_seconds_from_now,
|
55
58
|
klass, *args)
|
59
|
+
unless number_of_seconds_from_now.is_a?(Numeric)
|
60
|
+
raise ArgumentError, 'Please supply a numeric number of seconds'
|
61
|
+
end
|
56
62
|
enqueue_at_with_queue(queue, Time.now + number_of_seconds_from_now,
|
57
63
|
klass, *args)
|
58
64
|
end
|
59
65
|
|
66
|
+
# Update the delayed timestamp of any matching delayed jobs or enqueue a
|
67
|
+
# new job if no matching jobs are found. Returns the number of delayed or
|
68
|
+
# enqueued jobs.
|
69
|
+
def delay_or_enqueue_at(timestamp, klass, *args)
|
70
|
+
count = remove_delayed(klass, *args)
|
71
|
+
count = 1 if count == 0
|
72
|
+
|
73
|
+
count.times do
|
74
|
+
enqueue_at(timestamp, klass, *args)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
# Identical to +delay_or_enqueue_at+, except it takes
|
79
|
+
# number_of_seconds_from_now instead of a timestamp
|
80
|
+
def delay_or_enqueue_in(number_of_seconds_from_now, klass, *args)
|
81
|
+
delay_or_enqueue_at(Time.now + number_of_seconds_from_now, klass, *args)
|
82
|
+
end
|
83
|
+
|
60
84
|
# Used internally to stuff the item into the schedule sorted list.
|
61
|
-
# +timestamp+ can be either in seconds or a datetime object
|
62
|
-
#
|
63
|
-
# that time, else false
|
85
|
+
# +timestamp+ can be either in seconds or a datetime object. The
|
86
|
+
# insertion time complexity is O(log(n)). Returns true if it's
|
87
|
+
# the first job to be scheduled at that time, else false.
|
64
88
|
def delayed_push(timestamp, item)
|
65
89
|
# First add this item to the list for this timestamp
|
66
90
|
redis.rpush("delayed:#{timestamp.to_i}", encode(item))
|
@@ -82,6 +106,7 @@ module Resque
|
|
82
106
|
end
|
83
107
|
|
84
108
|
# Returns the size of the delayed queue schedule
|
109
|
+
# this does not represent the number of items in the queue to be scheduled
|
85
110
|
def delayed_queue_schedule_size
|
86
111
|
redis.zcard :delayed_queue_schedule
|
87
112
|
end
|
@@ -128,10 +153,7 @@ module Resque
|
|
128
153
|
Array(redis.zrange(:delayed_queue_schedule, 0, -1)).each do |item|
|
129
154
|
key = "delayed:#{item}"
|
130
155
|
items = redis.lrange(key, 0, -1)
|
131
|
-
redis.
|
132
|
-
items.each { |ts_item| redis.del("timestamps:#{ts_item}") }
|
133
|
-
end
|
134
|
-
redis.del key
|
156
|
+
redis.del(key, items.map { |ts_item| "timestamps:#{ts_item}" })
|
135
157
|
end
|
136
158
|
|
137
159
|
redis.del :delayed_queue_schedule
|
@@ -143,6 +165,11 @@ module Resque
|
|
143
165
|
remove_delayed_job(search)
|
144
166
|
end
|
145
167
|
|
168
|
+
def remove_delayed_in_queue(klass, queue, *args)
|
169
|
+
search = encode(job_to_hash_with_queue(queue, klass, args))
|
170
|
+
remove_delayed_job(search)
|
171
|
+
end
|
172
|
+
|
146
173
|
# Given an encoded item, enqueue it now
|
147
174
|
def enqueue_delayed(klass, *args)
|
148
175
|
hash = job_to_hash(klass, args)
|
@@ -151,6 +178,13 @@ module Resque
|
|
151
178
|
end
|
152
179
|
end
|
153
180
|
|
181
|
+
def enqueue_delayed_with_queue(klass, queue, *args)
|
182
|
+
hash = job_to_hash_with_queue(queue, klass, args)
|
183
|
+
remove_delayed_in_queue(klass, queue, *args).times do
|
184
|
+
Resque::Scheduler.enqueue_from_config(hash)
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
154
188
|
# Given a block, remove jobs that return true from a block
|
155
189
|
#
|
156
190
|
# This allows for removal of delayed jobs that have arguments matching
|
@@ -175,7 +209,15 @@ module Resque
|
|
175
209
|
found_jobs.reduce(0) do |sum, encoded_job|
|
176
210
|
decoded_job = decode(encoded_job)
|
177
211
|
klass = Util.constantize(decoded_job['class'])
|
178
|
-
|
212
|
+
queue = decoded_job['queue']
|
213
|
+
|
214
|
+
if queue
|
215
|
+
jobs_queued = enqueue_delayed_with_queue(klass, queue, *decoded_job['args'])
|
216
|
+
else
|
217
|
+
jobs_queued = enqueue_delayed(klass, *decoded_job['args'])
|
218
|
+
end
|
219
|
+
|
220
|
+
jobs_queued + sum
|
179
221
|
end
|
180
222
|
end
|
181
223
|
|
@@ -190,9 +232,9 @@ module Resque
|
|
190
232
|
|
191
233
|
# Beyond 100 there's almost no improvement in speed
|
192
234
|
found = timestamps.each_slice(100).map do |ts_group|
|
193
|
-
jobs = redis.pipelined do |
|
235
|
+
jobs = redis.pipelined do |pipeline|
|
194
236
|
ts_group.each do |ts|
|
195
|
-
|
237
|
+
pipeline.lrange("delayed:#{ts}", 0, -1)
|
196
238
|
end
|
197
239
|
end
|
198
240
|
|
@@ -265,18 +307,23 @@ module Resque
|
|
265
307
|
{ class: klass.to_s, args: args, queue: queue }
|
266
308
|
end
|
267
309
|
|
310
|
+
# Removes a job from the queue, but not modify the timestamp schedule. This method
|
311
|
+
# will not effect the output of `delayed_queue_schedule_size`
|
268
312
|
def remove_delayed_job(encoded_job)
|
269
313
|
return 0 if Resque.inline?
|
270
314
|
|
271
315
|
timestamps = redis.smembers("timestamps:#{encoded_job}")
|
272
316
|
|
273
|
-
replies = redis.pipelined do
|
317
|
+
replies = redis.pipelined do |pipeline|
|
274
318
|
timestamps.each do |key|
|
275
|
-
|
276
|
-
|
319
|
+
pipeline.lrem(key, 0, encoded_job)
|
320
|
+
pipeline.srem("timestamps:#{encoded_job}", key)
|
277
321
|
end
|
278
322
|
end
|
279
323
|
|
324
|
+
# timestamp key is not removed from the schedule, this is done later
|
325
|
+
# by the scheduler loop
|
326
|
+
|
280
327
|
return 0 if replies.nil? || replies.empty?
|
281
328
|
replies.each_slice(2).map(&:first).inject(:+)
|
282
329
|
end
|
@@ -287,9 +334,9 @@ module Resque
|
|
287
334
|
redis.watch(key) do
|
288
335
|
if redis.llen(key).to_i == 0
|
289
336
|
# If the list is empty, remove it.
|
290
|
-
redis.multi do
|
291
|
-
|
292
|
-
|
337
|
+
redis.multi do |transaction|
|
338
|
+
transaction.del(key)
|
339
|
+
transaction.zrem(:delayed_queue_schedule, timestamp.to_i)
|
293
340
|
end
|
294
341
|
else
|
295
342
|
redis.redis.unwatch
|
data/lib/resque/scheduler/env.rb
CHANGED
@@ -38,12 +38,8 @@ module Resque
|
|
38
38
|
true
|
39
39
|
end
|
40
40
|
|
41
|
-
unless Process.respond_to?('daemon')
|
42
|
-
abort 'background option is set, which requires ruby >= 1.9'
|
43
|
-
end
|
44
|
-
|
45
41
|
Process.daemon(true, !Resque::Scheduler.quiet)
|
46
|
-
Resque.redis.
|
42
|
+
Resque.redis._client.reconnect
|
47
43
|
end
|
48
44
|
|
49
45
|
def setup_pid_file
|
@@ -64,13 +60,13 @@ module Resque
|
|
64
60
|
|
65
61
|
c.dynamic = !!options[:dynamic] if options.key?(:dynamic)
|
66
62
|
|
67
|
-
c.env = options[:env] if options.key(:env)
|
63
|
+
c.env = options[:env] if options.key?(:env)
|
68
64
|
|
69
65
|
c.logfile = options[:logfile] if options.key?(:logfile)
|
70
66
|
|
71
67
|
c.logformat = options[:logformat] if options.key?(:logformat)
|
72
68
|
|
73
|
-
if psleep = options[:poll_sleep_amount] && !psleep.nil?
|
69
|
+
if (psleep = options[:poll_sleep_amount]) && !psleep.nil?
|
74
70
|
c.poll_sleep_amount = Float(psleep)
|
75
71
|
end
|
76
72
|
|
@@ -43,7 +43,7 @@ module Resque
|
|
43
43
|
@locked_sha = nil if refresh
|
44
44
|
|
45
45
|
@locked_sha ||=
|
46
|
-
Resque.redis.script(:load, <<-EOF.gsub(/^ {14}/, ''))
|
46
|
+
Resque.data_store.redis.script(:load, <<-EOF.gsub(/^ {14}/, ''))
|
47
47
|
if redis.call('GET', KEYS[1]) == ARGV[1]
|
48
48
|
then
|
49
49
|
redis.call('EXPIRE', KEYS[1], #{timeout})
|
@@ -62,7 +62,7 @@ module Resque
|
|
62
62
|
@acquire_sha = nil if refresh
|
63
63
|
|
64
64
|
@acquire_sha ||=
|
65
|
-
Resque.redis.script(:load, <<-EOF.gsub(/^ {14}/, ''))
|
65
|
+
Resque.data_store.redis.script(:load, <<-EOF.gsub(/^ {14}/, ''))
|
66
66
|
if redis.call('SETNX', KEYS[1], ARGV[1]) == 1
|
67
67
|
then
|
68
68
|
redis.call('EXPIRE', KEYS[1], #{timeout})
|
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
# ### Locking the scheduler process
|
4
4
|
#
|
5
|
-
# There are two places in resque-scheduler that need to be
|
5
|
+
# There are two places in resque-scheduler that need to be synchronized in order
|
6
6
|
# to be able to run redundant scheduler processes while ensuring jobs don't get
|
7
7
|
# queued multiple times when the master process changes.
|
8
8
|
#
|
@@ -76,7 +76,7 @@ module Resque
|
|
76
76
|
|
77
77
|
def release_master_lock
|
78
78
|
master_lock.release
|
79
|
-
rescue
|
79
|
+
rescue *INTERMITTENT_ERRORS
|
80
80
|
@master_lock = nil
|
81
81
|
end
|
82
82
|
|
@@ -97,7 +97,7 @@ module Resque
|
|
97
97
|
end
|
98
98
|
|
99
99
|
def redis_master_version
|
100
|
-
Resque.redis.info['redis_version'].to_f
|
100
|
+
Resque.data_store.redis.info['redis_version'].to_f
|
101
101
|
end
|
102
102
|
end
|
103
103
|
end
|
@@ -36,7 +36,7 @@ module Resque
|
|
36
36
|
# :args can be any yaml which will be converted to a ruby literal and
|
37
37
|
# passed in a params. (optional)
|
38
38
|
#
|
39
|
-
# :
|
39
|
+
# :rails_env is the list of envs where the job gets loaded. Envs are
|
40
40
|
# comma separated (optional)
|
41
41
|
#
|
42
42
|
# :description is just that, a description of the job (optional). If
|
@@ -101,12 +101,13 @@ module Resque
|
|
101
101
|
end
|
102
102
|
|
103
103
|
# remove a given schedule by name
|
104
|
-
|
104
|
+
# Preventing a reload is optional and available to batch operations
|
105
|
+
def remove_schedule(name, reload = true)
|
105
106
|
non_persistent_schedules.delete(name)
|
106
107
|
redis.hdel(:persistent_schedules, name)
|
107
108
|
redis.sadd(:schedules_changed, name)
|
108
109
|
|
109
|
-
reload_schedule!
|
110
|
+
reload_schedule! if reload
|
110
111
|
end
|
111
112
|
|
112
113
|
private
|
@@ -1,9 +1,9 @@
|
|
1
1
|
<h1>Delayed Jobs</h1>
|
2
|
-
|
2
|
+
<% size = resque.delayed_queue_schedule_size %>
|
3
3
|
|
4
4
|
<%= scheduler_view :search_form, layout: false %>
|
5
5
|
|
6
|
-
<p style="
|
6
|
+
<p style="color: red; font-weight: bold;">
|
7
7
|
<%= @error_message %>
|
8
8
|
</p>
|
9
9
|
|
@@ -46,7 +46,7 @@
|
|
46
46
|
<td><%= h(show_job_arguments(job['args'])) if job && delayed_timestamp_size == 1 %></td>
|
47
47
|
<td>
|
48
48
|
<% if job %>
|
49
|
-
<a href="<%=u URI("/delayed/jobs/#{job['class']}?args=" +
|
49
|
+
<a href="<%= u URI("/delayed/jobs/#{CGI.escape(job['class'])}?args=" + CGI.escape(job['args'].to_json)) %>">All schedules</a>
|
50
50
|
<% end %>
|
51
51
|
</td>
|
52
52
|
</tr>
|
@@ -55,7 +55,7 @@
|
|
55
55
|
|
56
56
|
<% if size > 0 %>
|
57
57
|
<br>
|
58
|
-
<form method="POST" action="<%=u 'delayed/clear'%>" class='clear-delayed'>
|
58
|
+
<form method="POST" action="<%= u 'delayed/clear' %>" class='clear-delayed'>
|
59
59
|
<input type='submit' name='' value='Clear Delayed Jobs' />
|
60
60
|
</form>
|
61
61
|
<% end %>
|
@@ -8,7 +8,7 @@
|
|
8
8
|
<br/> Current master: <%= Resque.redis.get(Resque::Scheduler.master_lock.key) %>
|
9
9
|
</p>
|
10
10
|
<p class='intro'>
|
11
|
-
|
11
|
+
The highlighted jobs are skipped for current environment.
|
12
12
|
</p>
|
13
13
|
<div style="overflow-y: auto; width:100%; padding: 0px 5px;">
|
14
14
|
<table>
|
@@ -29,7 +29,7 @@
|
|
29
29
|
<% Resque.schedule.keys.sort.each_with_index do |name, index| %>
|
30
30
|
<% config = Resque.schedule[name] %>
|
31
31
|
<tr style="<%= scheduled_in_this_env?(name) ? '' : 'color: #9F6000;background: #FEEFB3;' %>">
|
32
|
-
|
32
|
+
<td style="padding-left: 15px;"><%= index + 1 %>.</td>
|
33
33
|
<% if Resque::Scheduler.dynamic %>
|
34
34
|
<td style="padding-top: 12px; padding-bottom: 2px; width: 10px">
|
35
35
|
<form action="<%= u "/schedule" %>" method="post" style="margin-left: 0">
|
@@ -87,7 +87,7 @@ module Resque
|
|
87
87
|
def delayed_jobs_klass
|
88
88
|
begin
|
89
89
|
klass = Resque::Scheduler::Util.constantize(params[:klass])
|
90
|
-
@args = JSON.load(
|
90
|
+
@args = JSON.load(CGI.unescape(params[:args]))
|
91
91
|
@timestamps = Resque.scheduled_at(klass, *@args)
|
92
92
|
rescue
|
93
93
|
@timestamps = []
|
@@ -10,13 +10,13 @@ module Resque
|
|
10
10
|
end
|
11
11
|
|
12
12
|
# For all signals, set the shutdown flag and wait for current
|
13
|
-
# poll/
|
13
|
+
# poll/enqueuing to finish (should be almost instant). In the
|
14
14
|
# case of sleeping, exit immediately.
|
15
15
|
def register_signal_handlers
|
16
16
|
(Signal.list.keys & %w(INT TERM USR1 USR2 QUIT)).each do |sig|
|
17
17
|
trap(sig) do
|
18
18
|
signal_queue << sig
|
19
|
-
# break sleep in the primary scheduler thread,
|
19
|
+
# break sleep in the primary scheduler thread, allowing
|
20
20
|
# the signal queue to get processed as soon as possible.
|
21
21
|
@th.wakeup if @th && @th.alive?
|
22
22
|
end
|
@@ -4,7 +4,7 @@ module Resque
|
|
4
4
|
module Scheduler
|
5
5
|
class Util
|
6
6
|
# In order to upgrade to resque(1.25) which has deprecated following
|
7
|
-
# methods, we just added these
|
7
|
+
# methods, we just added these useful helpers back to use in Resque
|
8
8
|
# Scheduler. refer to:
|
9
9
|
# https://github.com/resque/resque-scheduler/pull/273
|
10
10
|
|
data/lib/resque/scheduler.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
# vim:fileencoding=utf-8
|
2
2
|
|
3
|
+
require 'redis/errors'
|
3
4
|
require 'rufus/scheduler'
|
4
5
|
require_relative 'scheduler/configuration'
|
5
6
|
require_relative 'scheduler/locking'
|
@@ -13,6 +14,9 @@ module Resque
|
|
13
14
|
autoload :Extension, 'resque/scheduler/extension'
|
14
15
|
autoload :Util, 'resque/scheduler/util'
|
15
16
|
autoload :VERSION, 'resque/scheduler/version'
|
17
|
+
INTERMITTENT_ERRORS = [
|
18
|
+
Errno::EAGAIN, Errno::ECONNRESET, Redis::CannotConnectError, Redis::TimeoutError
|
19
|
+
].freeze
|
16
20
|
|
17
21
|
private
|
18
22
|
|
@@ -44,13 +48,7 @@ module Resque
|
|
44
48
|
$stdout.sync = true
|
45
49
|
$stderr.sync = true
|
46
50
|
|
47
|
-
|
48
|
-
# If dynamic is set, load that schedule otherwise use normal load
|
49
|
-
if dynamic
|
50
|
-
reload_schedule!
|
51
|
-
else
|
52
|
-
load_schedule!
|
53
|
-
end
|
51
|
+
was_master = nil
|
54
52
|
|
55
53
|
begin
|
56
54
|
@th = Thread.current
|
@@ -58,11 +56,21 @@ module Resque
|
|
58
56
|
# Now start the scheduling part of the loop.
|
59
57
|
loop do
|
60
58
|
begin
|
61
|
-
|
59
|
+
# Check on changes to master/child
|
60
|
+
@am_master = master?
|
61
|
+
if am_master != was_master
|
62
|
+
procline am_master ? 'Master scheduler' : 'Child scheduler'
|
63
|
+
|
64
|
+
# Load schedule because changed
|
65
|
+
reload_schedule!
|
66
|
+
end
|
67
|
+
|
68
|
+
if am_master
|
62
69
|
handle_delayed_items
|
63
70
|
update_schedule if dynamic
|
64
71
|
end
|
65
|
-
|
72
|
+
was_master = am_master
|
73
|
+
rescue *INTERMITTENT_ERRORS => e
|
66
74
|
log! e.message
|
67
75
|
release_master_lock
|
68
76
|
end
|
@@ -99,7 +107,7 @@ module Resque
|
|
99
107
|
Resque.schedule.each do |name, config|
|
100
108
|
load_schedule_job(name, config)
|
101
109
|
end
|
102
|
-
Resque.redis.del(:schedules_changed)
|
110
|
+
Resque.redis.del(:schedules_changed) if am_master && dynamic
|
103
111
|
procline 'Schedules Loaded'
|
104
112
|
end
|
105
113
|
|
@@ -202,7 +210,7 @@ module Resque
|
|
202
210
|
loop do
|
203
211
|
handle_shutdown do
|
204
212
|
# Continually check that it is still the master
|
205
|
-
item = enqueue_next_item(timestamp) if
|
213
|
+
item = enqueue_next_item(timestamp) if am_master
|
206
214
|
end
|
207
215
|
# continue processing until there are no more ready items in this
|
208
216
|
# timestamp
|
@@ -243,7 +251,7 @@ module Resque
|
|
243
251
|
if job_klass && job_klass != 'Resque::Job'
|
244
252
|
# The custom job class API must offer a static "scheduled" method. If
|
245
253
|
# the custom job class can not be constantized (via a requeue call
|
246
|
-
# from the web perhaps), fall back to
|
254
|
+
# from the web perhaps), fall back to enqueuing normally via
|
247
255
|
# Resque::Job.create.
|
248
256
|
begin
|
249
257
|
Resque::Scheduler::Util.constantize(job_klass).scheduled(
|
@@ -369,7 +377,6 @@ module Resque
|
|
369
377
|
|
370
378
|
def stop_rufus_scheduler
|
371
379
|
rufus_scheduler.shutdown(:wait)
|
372
|
-
rufus_scheduler.join
|
373
380
|
end
|
374
381
|
|
375
382
|
def before_shutdown
|
@@ -420,10 +427,10 @@ module Resque
|
|
420
427
|
private
|
421
428
|
|
422
429
|
def enqueue_recurring(name, config)
|
423
|
-
if
|
430
|
+
if am_master
|
424
431
|
log! "queueing #{config['class']} (#{name})"
|
425
|
-
Resque.last_enqueued_at(name, Time.now.to_s)
|
426
432
|
enqueue(config)
|
433
|
+
Resque.last_enqueued_at(name, Time.now.to_s)
|
427
434
|
end
|
428
435
|
end
|
429
436
|
|
@@ -442,6 +449,11 @@ module Resque
|
|
442
449
|
def internal_name
|
443
450
|
"resque-scheduler-#{Resque::Scheduler::VERSION}"
|
444
451
|
end
|
452
|
+
|
453
|
+
def am_master
|
454
|
+
@am_master = master? unless defined?(@am_master)
|
455
|
+
@am_master
|
456
|
+
end
|
445
457
|
end
|
446
458
|
end
|
447
459
|
end
|
data/resque-scheduler.gemspec
CHANGED
@@ -11,12 +11,14 @@ Gem::Specification.new do |spec|
|
|
11
11
|
Simon Eskildsen
|
12
12
|
Ryan Biesemeyer
|
13
13
|
Dan Buch
|
14
|
+
Michael Bianco
|
14
15
|
EOF
|
15
16
|
spec.email = %w(
|
16
17
|
bvandenbos@gmail.com
|
17
18
|
sirup@sirupsen.com
|
18
19
|
ryan@yaauie.com
|
19
20
|
dan@meatballhat.com
|
21
|
+
mike@mikebian.co
|
20
22
|
)
|
21
23
|
spec.summary = 'Light weight job scheduling on top of Resque'
|
22
24
|
spec.description = <<-DESCRIPTION
|
@@ -24,13 +26,16 @@ Gem::Specification.new do |spec|
|
|
24
26
|
Adds methods enqueue_at/enqueue_in to schedule jobs in the future.
|
25
27
|
Also supports queueing jobs on a fixed, cron-like schedule.
|
26
28
|
DESCRIPTION
|
27
|
-
spec.homepage = '
|
29
|
+
spec.homepage = 'https://github.com/resque/resque-scheduler'
|
28
30
|
spec.license = 'MIT'
|
31
|
+
spec.metadata['rubygems_mfa_required'] = 'true'
|
32
|
+
|
33
|
+
spec.required_ruby_version = '>= 2.3.0'
|
29
34
|
|
30
35
|
spec.files = `git ls-files -z`.split("\0").reject do |f|
|
31
36
|
f.match(%r{^(test|spec|features|examples|bin|tasks)/}) ||
|
32
|
-
f.match(/^(Vagrantfile|Gemfile\.lock
|
33
|
-
f.match(/^\.(rubocop|simplecov|
|
37
|
+
f.match(/^(Vagrantfile|Gemfile\.lock)/) ||
|
38
|
+
f.match(/^\.(rubocop|simplecov|vagrant|gitignore)/)
|
34
39
|
end
|
35
40
|
spec.bindir = 'exe'
|
36
41
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
@@ -38,7 +43,6 @@ Gem::Specification.new do |spec|
|
|
38
43
|
|
39
44
|
spec.add_development_dependency 'bundler'
|
40
45
|
spec.add_development_dependency 'json'
|
41
|
-
spec.add_development_dependency 'kramdown'
|
42
46
|
spec.add_development_dependency 'minitest'
|
43
47
|
spec.add_development_dependency 'mocha'
|
44
48
|
spec.add_development_dependency 'pry'
|
@@ -47,14 +51,16 @@ Gem::Specification.new do |spec|
|
|
47
51
|
spec.add_development_dependency 'simplecov'
|
48
52
|
spec.add_development_dependency 'test-unit'
|
49
53
|
spec.add_development_dependency 'yard'
|
50
|
-
spec.add_development_dependency '
|
54
|
+
spec.add_development_dependency 'timecop'
|
51
55
|
|
52
56
|
# We pin rubocop because new cops have a tendency to result in false-y
|
53
57
|
# positives for new contributors, which is not a nice experience.
|
54
58
|
spec.add_development_dependency 'rubocop', '~> 0.40.0'
|
55
59
|
|
56
60
|
spec.add_runtime_dependency 'mono_logger', '~> 1.0'
|
57
|
-
spec.add_runtime_dependency 'redis', '>= 3.3'
|
58
|
-
spec.add_runtime_dependency 'resque', '
|
59
|
-
|
61
|
+
spec.add_runtime_dependency 'redis', '>= 3.3'
|
62
|
+
spec.add_runtime_dependency 'resque', '>= 1.27'
|
63
|
+
# rufus-scheduler v3.7 causes a failure in test/multi_process_test.rb
|
64
|
+
# rufus-scheduler v3.3 is missing a to_local method which fails tests
|
65
|
+
spec.add_runtime_dependency 'rufus-scheduler', '~> 3.2', '!= 3.3'
|
60
66
|
end
|