resque-scheduler 4.4.0 → 4.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- 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 +82 -0
- data/AUTHORS.md +8 -0
- data/CHANGELOG.md +81 -2
- data/Gemfile +20 -3
- data/README.md +90 -19
- data/Rakefile +2 -5
- data/lib/resque/scheduler/cli.rb +2 -1
- data/lib/resque/scheduler/configuration.rb +45 -9
- data/lib/resque/scheduler/delaying_extensions.rb +86 -47
- data/lib/resque/scheduler/env.rb +5 -5
- data/lib/resque/scheduler/lock/base.rb +2 -2
- data/lib/resque/scheduler/locking.rb +1 -1
- data/lib/resque/scheduler/logger_builder.rb +17 -6
- data/lib/resque/scheduler/plugin.rb +9 -0
- data/lib/resque/scheduler/scheduling_extensions.rb +6 -5
- data/lib/resque/scheduler/server/views/delayed.erb +12 -11
- data/lib/resque/scheduler/server/views/delayed_schedules.erb +1 -1
- 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 +2 -5
- 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 +81 -18
- data/resque-scheduler.gemspec +15 -7
- metadata +25 -23
@@ -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'
|
@@ -205,16 +206,80 @@ module Resque
|
|
205
206
|
|
206
207
|
# Enqueues all delayed jobs for a timestamp
|
207
208
|
def enqueue_delayed_items_for_timestamp(timestamp)
|
208
|
-
|
209
|
+
count = 0
|
210
|
+
batch_size = delayed_requeue_batch_size
|
211
|
+
actual_batch_size = nil
|
212
|
+
|
213
|
+
log "Processing delayed items for timestamp #{timestamp}, in batches of #{batch_size}"
|
214
|
+
|
209
215
|
loop do
|
210
216
|
handle_shutdown do
|
211
217
|
# Continually check that it is still the master
|
212
|
-
|
218
|
+
if am_master
|
219
|
+
actual_batch_size = enqueue_items_in_batch_for_timestamp(timestamp,
|
220
|
+
batch_size)
|
221
|
+
end
|
213
222
|
end
|
214
|
-
|
215
|
-
|
216
|
-
|
223
|
+
|
224
|
+
count += actual_batch_size
|
225
|
+
log "queued #{count} jobs" if actual_batch_size != -1
|
226
|
+
|
227
|
+
# continue processing until there are no more items in this
|
228
|
+
# timestamp. If we don't have a full batch, this is the last one.
|
229
|
+
# This also breaks us in the event of a redis transaction failure
|
230
|
+
# i.e. enqueue_items_in_batch_for_timestamp returned -1
|
231
|
+
break if actual_batch_size < batch_size
|
217
232
|
end
|
233
|
+
|
234
|
+
log "finished queueing #{count} total jobs for timestamp #{timestamp}" if count != -1
|
235
|
+
end
|
236
|
+
|
237
|
+
def timestamp_key(timestamp)
|
238
|
+
"delayed:#{timestamp.to_i}"
|
239
|
+
end
|
240
|
+
|
241
|
+
def enqueue_items_in_batch_for_timestamp(timestamp, batch_size)
|
242
|
+
timestamp_bucket_key = timestamp_key(timestamp)
|
243
|
+
|
244
|
+
encoded_jobs_to_requeue = Resque.redis.lrange(timestamp_bucket_key, 0, batch_size - 1)
|
245
|
+
|
246
|
+
# Watch is used to ensure that the timestamp bucket we are operating on
|
247
|
+
# is not altered by any other clients between the watch call and when we call exec
|
248
|
+
# (to execute the multi block). We should error catch on the redis.exec return value
|
249
|
+
# as that will indicate if the entire transaction was aborted or not. Though we should
|
250
|
+
# be safe as our ltrim is inside the multi block and therefore also would have been
|
251
|
+
# aborted. So nothing would have been queued, but also nothing lost from the bucket.
|
252
|
+
watch_result = Resque.redis.watch(timestamp_bucket_key) do
|
253
|
+
Resque.redis.multi do |pipeline|
|
254
|
+
encoded_jobs_to_requeue.each do |encoded_job|
|
255
|
+
pipeline.srem("timestamps:#{encoded_job}", timestamp_bucket_key)
|
256
|
+
|
257
|
+
decoded_job = Resque.decode(encoded_job)
|
258
|
+
enqueue(decoded_job)
|
259
|
+
end
|
260
|
+
|
261
|
+
pipeline.ltrim(timestamp_bucket_key, batch_size, -1)
|
262
|
+
end
|
263
|
+
end
|
264
|
+
|
265
|
+
# Did the multi block successfully remove from this timestamp and enqueue the jobs?
|
266
|
+
success = !watch_result.nil?
|
267
|
+
|
268
|
+
# If this was the last batch in this timestamp bucket, clean up
|
269
|
+
if success && encoded_jobs_to_requeue.count < batch_size
|
270
|
+
Resque.clean_up_timestamp(timestamp_bucket_key, timestamp)
|
271
|
+
end
|
272
|
+
|
273
|
+
unless success
|
274
|
+
# Our batched transaction failed in Redis due to the timestamp_bucket_key value
|
275
|
+
# being modified while we built our multi block. We return -1 to ensure we break
|
276
|
+
# out of the loop iterating on this timestamp so it can be re-processed via the
|
277
|
+
# loop in handle_delayed_items.
|
278
|
+
return -1
|
279
|
+
end
|
280
|
+
|
281
|
+
# will return 0 if none were left to batch
|
282
|
+
encoded_jobs_to_requeue.count
|
218
283
|
end
|
219
284
|
|
220
285
|
def enqueue(config)
|
@@ -250,7 +315,7 @@ module Resque
|
|
250
315
|
if job_klass && job_klass != 'Resque::Job'
|
251
316
|
# The custom job class API must offer a static "scheduled" method. If
|
252
317
|
# the custom job class can not be constantized (via a requeue call
|
253
|
-
# from the web perhaps), fall back to
|
318
|
+
# from the web perhaps), fall back to enqueuing normally via
|
254
319
|
# Resque::Job.create.
|
255
320
|
begin
|
256
321
|
Resque::Scheduler::Util.constantize(job_klass).scheduled(
|
@@ -266,17 +331,16 @@ module Resque
|
|
266
331
|
# for non-existent classes (for example: running scheduler in
|
267
332
|
# one app that schedules for another.
|
268
333
|
if Class === klass
|
269
|
-
Resque::Scheduler::Plugin.
|
270
|
-
klass, *params
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
Resque.enqueue_to(queue, klass, *params)
|
334
|
+
Resque::Scheduler::Plugin.process_schedule_hooks(klass, *params) do
|
335
|
+
Resque::Scheduler::Plugin.run_before_delayed_enqueue_hooks(klass, *params)
|
336
|
+
# If the class is a custom job class, call self#scheduled on it.
|
337
|
+
# This allows you to do things like Resque.enqueue_at(timestamp,
|
338
|
+
# CustomJobClass). Otherwise, pass off to Resque.
|
339
|
+
if klass.respond_to?(:scheduled)
|
340
|
+
klass.scheduled(queue, klass_name, *params)
|
341
|
+
else
|
342
|
+
Resque.enqueue_to(queue, klass, *params)
|
343
|
+
end
|
280
344
|
end
|
281
345
|
else
|
282
346
|
# This will not run the before_hooks in rescue, but will at least
|
@@ -376,7 +440,6 @@ module Resque
|
|
376
440
|
|
377
441
|
def stop_rufus_scheduler
|
378
442
|
rufus_scheduler.shutdown(:wait)
|
379
|
-
rufus_scheduler.join
|
380
443
|
end
|
381
444
|
|
382
445
|
def before_shutdown
|
data/resque-scheduler.gemspec
CHANGED
@@ -11,12 +11,16 @@ Gem::Specification.new do |spec|
|
|
11
11
|
Simon Eskildsen
|
12
12
|
Ryan Biesemeyer
|
13
13
|
Dan Buch
|
14
|
+
Michael Bianco
|
15
|
+
Patrick Tulskie
|
14
16
|
EOF
|
15
17
|
spec.email = %w(
|
16
18
|
bvandenbos@gmail.com
|
17
19
|
sirup@sirupsen.com
|
18
20
|
ryan@yaauie.com
|
19
21
|
dan@meatballhat.com
|
22
|
+
mike@mikebian.co
|
23
|
+
patricktulskie@gmail.com
|
20
24
|
)
|
21
25
|
spec.summary = 'Light weight job scheduling on top of Resque'
|
22
26
|
spec.description = <<-DESCRIPTION
|
@@ -24,13 +28,16 @@ Gem::Specification.new do |spec|
|
|
24
28
|
Adds methods enqueue_at/enqueue_in to schedule jobs in the future.
|
25
29
|
Also supports queueing jobs on a fixed, cron-like schedule.
|
26
30
|
DESCRIPTION
|
27
|
-
spec.homepage = '
|
31
|
+
spec.homepage = 'https://github.com/resque/resque-scheduler'
|
28
32
|
spec.license = 'MIT'
|
33
|
+
spec.metadata['rubygems_mfa_required'] = 'true'
|
34
|
+
|
35
|
+
spec.required_ruby_version = '>= 2.3.0'
|
29
36
|
|
30
37
|
spec.files = `git ls-files -z`.split("\0").reject do |f|
|
31
38
|
f.match(%r{^(test|spec|features|examples|bin|tasks)/}) ||
|
32
|
-
f.match(/^(Vagrantfile|Gemfile\.lock
|
33
|
-
f.match(/^\.(rubocop|simplecov|
|
39
|
+
f.match(/^(Vagrantfile|Gemfile\.lock)/) ||
|
40
|
+
f.match(/^\.(rubocop|simplecov|vagrant|gitignore)/)
|
34
41
|
end
|
35
42
|
spec.bindir = 'exe'
|
36
43
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
@@ -38,7 +45,6 @@ Gem::Specification.new do |spec|
|
|
38
45
|
|
39
46
|
spec.add_development_dependency 'bundler'
|
40
47
|
spec.add_development_dependency 'json'
|
41
|
-
spec.add_development_dependency 'kramdown'
|
42
48
|
spec.add_development_dependency 'minitest'
|
43
49
|
spec.add_development_dependency 'mocha'
|
44
50
|
spec.add_development_dependency 'pry'
|
@@ -47,7 +53,7 @@ Gem::Specification.new do |spec|
|
|
47
53
|
spec.add_development_dependency 'simplecov'
|
48
54
|
spec.add_development_dependency 'test-unit'
|
49
55
|
spec.add_development_dependency 'yard'
|
50
|
-
spec.add_development_dependency '
|
56
|
+
spec.add_development_dependency 'timecop'
|
51
57
|
|
52
58
|
# We pin rubocop because new cops have a tendency to result in false-y
|
53
59
|
# positives for new contributors, which is not a nice experience.
|
@@ -55,6 +61,8 @@ Gem::Specification.new do |spec|
|
|
55
61
|
|
56
62
|
spec.add_runtime_dependency 'mono_logger', '~> 1.0'
|
57
63
|
spec.add_runtime_dependency 'redis', '>= 3.3'
|
58
|
-
spec.add_runtime_dependency 'resque', '>= 1.
|
59
|
-
|
64
|
+
spec.add_runtime_dependency 'resque', '>= 1.27'
|
65
|
+
# rufus-scheduler v3.7 causes a failure in test/multi_process_test.rb
|
66
|
+
# rufus-scheduler v3.3 is missing a to_local method which fails tests
|
67
|
+
spec.add_runtime_dependency 'rufus-scheduler', '~> 3.2', '!= 3.3'
|
60
68
|
end
|
metadata
CHANGED
@@ -1,17 +1,19 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: resque-scheduler
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.
|
4
|
+
version: 4.11.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ben VandenBos
|
8
8
|
- Simon Eskildsen
|
9
9
|
- Ryan Biesemeyer
|
10
10
|
- Dan Buch
|
11
|
+
- Michael Bianco
|
12
|
+
- Patrick Tulskie
|
11
13
|
autorequire:
|
12
14
|
bindir: exe
|
13
15
|
cert_chain: []
|
14
|
-
date:
|
16
|
+
date: 2024-12-30 00:00:00.000000000 Z
|
15
17
|
dependencies:
|
16
18
|
- !ruby/object:Gem::Dependency
|
17
19
|
name: bundler
|
@@ -41,20 +43,6 @@ dependencies:
|
|
41
43
|
- - ">="
|
42
44
|
- !ruby/object:Gem::Version
|
43
45
|
version: '0'
|
44
|
-
- !ruby/object:Gem::Dependency
|
45
|
-
name: kramdown
|
46
|
-
requirement: !ruby/object:Gem::Requirement
|
47
|
-
requirements:
|
48
|
-
- - ">="
|
49
|
-
- !ruby/object:Gem::Version
|
50
|
-
version: '0'
|
51
|
-
type: :development
|
52
|
-
prerelease: false
|
53
|
-
version_requirements: !ruby/object:Gem::Requirement
|
54
|
-
requirements:
|
55
|
-
- - ">="
|
56
|
-
- !ruby/object:Gem::Version
|
57
|
-
version: '0'
|
58
46
|
- !ruby/object:Gem::Dependency
|
59
47
|
name: minitest
|
60
48
|
requirement: !ruby/object:Gem::Requirement
|
@@ -168,7 +156,7 @@ dependencies:
|
|
168
156
|
- !ruby/object:Gem::Version
|
169
157
|
version: '0'
|
170
158
|
- !ruby/object:Gem::Dependency
|
171
|
-
name:
|
159
|
+
name: timecop
|
172
160
|
requirement: !ruby/object:Gem::Requirement
|
173
161
|
requirements:
|
174
162
|
- - ">="
|
@@ -229,14 +217,14 @@ dependencies:
|
|
229
217
|
requirements:
|
230
218
|
- - ">="
|
231
219
|
- !ruby/object:Gem::Version
|
232
|
-
version: '1.
|
220
|
+
version: '1.27'
|
233
221
|
type: :runtime
|
234
222
|
prerelease: false
|
235
223
|
version_requirements: !ruby/object:Gem::Requirement
|
236
224
|
requirements:
|
237
225
|
- - ">="
|
238
226
|
- !ruby/object:Gem::Version
|
239
|
-
version: '1.
|
227
|
+
version: '1.27'
|
240
228
|
- !ruby/object:Gem::Dependency
|
241
229
|
name: rufus-scheduler
|
242
230
|
requirement: !ruby/object:Gem::Requirement
|
@@ -244,6 +232,9 @@ dependencies:
|
|
244
232
|
- - "~>"
|
245
233
|
- !ruby/object:Gem::Version
|
246
234
|
version: '3.2'
|
235
|
+
- - "!="
|
236
|
+
- !ruby/object:Gem::Version
|
237
|
+
version: '3.3'
|
247
238
|
type: :runtime
|
248
239
|
prerelease: false
|
249
240
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -251,6 +242,9 @@ dependencies:
|
|
251
242
|
- - "~>"
|
252
243
|
- !ruby/object:Gem::Version
|
253
244
|
version: '3.2'
|
245
|
+
- - "!="
|
246
|
+
- !ruby/object:Gem::Version
|
247
|
+
version: '3.3'
|
254
248
|
description: |2
|
255
249
|
Light weight job scheduling on top of Resque.
|
256
250
|
Adds methods enqueue_at/enqueue_in to schedule jobs in the future.
|
@@ -260,11 +254,18 @@ email:
|
|
260
254
|
- sirup@sirupsen.com
|
261
255
|
- ryan@yaauie.com
|
262
256
|
- dan@meatballhat.com
|
257
|
+
- mike@mikebian.co
|
258
|
+
- patricktulskie@gmail.com
|
263
259
|
executables:
|
264
260
|
- resque-scheduler
|
265
261
|
extensions: []
|
266
262
|
extra_rdoc_files: []
|
267
263
|
files:
|
264
|
+
- ".github/dependabot.yml"
|
265
|
+
- ".github/funding.yml"
|
266
|
+
- ".github/workflows/codeql-analysis.yml"
|
267
|
+
- ".github/workflows/rubocop.yml"
|
268
|
+
- ".github/workflows/ruby.yml"
|
268
269
|
- AUTHORS.md
|
269
270
|
- CHANGELOG.md
|
270
271
|
- CODE_OF_CONDUCT.md
|
@@ -303,10 +304,11 @@ files:
|
|
303
304
|
- lib/resque/scheduler/util.rb
|
304
305
|
- lib/resque/scheduler/version.rb
|
305
306
|
- resque-scheduler.gemspec
|
306
|
-
homepage:
|
307
|
+
homepage: https://github.com/resque/resque-scheduler
|
307
308
|
licenses:
|
308
309
|
- MIT
|
309
|
-
metadata:
|
310
|
+
metadata:
|
311
|
+
rubygems_mfa_required: 'true'
|
310
312
|
post_install_message:
|
311
313
|
rdoc_options: []
|
312
314
|
require_paths:
|
@@ -315,14 +317,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
315
317
|
requirements:
|
316
318
|
- - ">="
|
317
319
|
- !ruby/object:Gem::Version
|
318
|
-
version:
|
320
|
+
version: 2.3.0
|
319
321
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
320
322
|
requirements:
|
321
323
|
- - ">="
|
322
324
|
- !ruby/object:Gem::Version
|
323
325
|
version: '0'
|
324
326
|
requirements: []
|
325
|
-
rubygems_version: 3.0.3
|
327
|
+
rubygems_version: 3.0.3.1
|
326
328
|
signing_key:
|
327
329
|
specification_version: 4
|
328
330
|
summary: Light weight job scheduling on top of Resque
|