resque-scheduler 4.3.1 → 4.5.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/workflows/rubocop.yml +27 -0
- data/.github/workflows/ruby.yml +48 -0
- data/AUTHORS.md +7 -0
- data/CHANGELOG.md +40 -2
- data/Gemfile +8 -0
- data/README.md +19 -14
- data/Rakefile +1 -5
- data/lib/resque/scheduler/delaying_extensions.rb +38 -6
- data/lib/resque/scheduler/env.rb +3 -3
- data/lib/resque/scheduler/lock/resilient.rb +2 -2
- data/lib/resque/scheduler/locking.rb +2 -2
- data/lib/resque/scheduler/scheduling_extensions.rb +4 -3
- data/lib/resque/scheduler/server/views/delayed.erb +1 -1
- data/lib/resque/scheduler/server/views/search_form.erb +1 -1
- data/lib/resque/scheduler/server.rb +1 -1
- data/lib/resque/scheduler/version.rb +1 -1
- data/lib/resque/scheduler.rb +26 -13
- data/resque-scheduler.gemspec +8 -4
- metadata +35 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 2c97d0ecaec5a456e20e91d98779f7792fafd99e09f1bfd85452234a01ba47c0
|
4
|
+
data.tar.gz: f3947f2446b6ddac4d5555d467a302a3032a08d3dd77bdc039253674f70a85e1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cbfefeb510538682d188284280ca56af1641de3dde1a63ad8b79b5a09dcc916dc902839782a9ad988421c77b84146a05b4077291aa754e24d07dc75440786c2e
|
7
|
+
data.tar.gz: 955193ba760e37bd6f58f94a4ba67edab755329a68e4deefa0466c822d3fbd3d057cf357a410bedf23fd145b687255b3fe783d44890d7d4dfd0307773c1baeb5
|
@@ -0,0 +1,27 @@
|
|
1
|
+
name: Rubocop
|
2
|
+
|
3
|
+
on:
|
4
|
+
push:
|
5
|
+
branches: [master]
|
6
|
+
pull_request:
|
7
|
+
branches: [master]
|
8
|
+
|
9
|
+
jobs:
|
10
|
+
rubocop:
|
11
|
+
name: Rubocop
|
12
|
+
runs-on: ${{ matrix.os }}
|
13
|
+
strategy:
|
14
|
+
matrix:
|
15
|
+
os: [ubuntu-latest]
|
16
|
+
ruby: [
|
17
|
+
2.4
|
18
|
+
]
|
19
|
+
|
20
|
+
steps:
|
21
|
+
- uses: actions/checkout@v2
|
22
|
+
- uses: ruby/setup-ruby@v1
|
23
|
+
with:
|
24
|
+
ruby-version: ${{ matrix.ruby }}
|
25
|
+
bundler-cache: true
|
26
|
+
- name: Ruby linter
|
27
|
+
run: bundle exec rubocop
|
@@ -0,0 +1,48 @@
|
|
1
|
+
name: CI
|
2
|
+
|
3
|
+
on:
|
4
|
+
push:
|
5
|
+
branches: [master]
|
6
|
+
pull_request:
|
7
|
+
branches: [master]
|
8
|
+
|
9
|
+
jobs:
|
10
|
+
test:
|
11
|
+
runs-on: ubuntu-latest
|
12
|
+
services:
|
13
|
+
redis:
|
14
|
+
image: redis
|
15
|
+
ports:
|
16
|
+
- 6379:6379
|
17
|
+
strategy:
|
18
|
+
fail-fast: false
|
19
|
+
matrix:
|
20
|
+
ruby-version:
|
21
|
+
- 2.3
|
22
|
+
- 2.4
|
23
|
+
- 2.5
|
24
|
+
- 2.6
|
25
|
+
- 2.7
|
26
|
+
- "3.0"
|
27
|
+
- head
|
28
|
+
- jruby-9.1.17.0
|
29
|
+
- jruby-9.2.9.0
|
30
|
+
- jruby-9.2.19.0
|
31
|
+
resque-version:
|
32
|
+
- "master"
|
33
|
+
- "~> 2.0.0"
|
34
|
+
- "~> 1.27"
|
35
|
+
env:
|
36
|
+
RESQUE: "${{ matrix.resque-version }}"
|
37
|
+
COVERAGE: 1
|
38
|
+
JRUBY_OPTS: ""
|
39
|
+
RUBYOPT: "-W0"
|
40
|
+
|
41
|
+
steps:
|
42
|
+
- uses: actions/checkout@v2
|
43
|
+
- uses: ruby/setup-ruby@v1
|
44
|
+
with:
|
45
|
+
ruby-version: "${{ matrix.ruby-version }}"
|
46
|
+
bundler-cache: true
|
47
|
+
- run: bundle exec rake
|
48
|
+
- run: bin/bundle_console_test.sh
|
data/AUTHORS.md
CHANGED
@@ -27,14 +27,17 @@ Resque Scheduler authors
|
|
27
27
|
- Harry Lascelles
|
28
28
|
- Henrik Nyh
|
29
29
|
- Hormoz Kheradmand
|
30
|
+
- Ian Davies
|
30
31
|
- James Le Cuirot
|
31
32
|
- Jarkko Mönkkönen
|
33
|
+
- Jimmy Chao
|
32
34
|
- John Crepezzi
|
33
35
|
- John Griffin
|
34
36
|
- Jon Larkowski and Les Hill
|
35
37
|
- Jonathan Conley
|
36
38
|
- Jonathan Hyman
|
37
39
|
- Jonathan Owens
|
40
|
+
- Jordan Gardner
|
38
41
|
- Joshua Szmajda
|
39
42
|
- Justin Weiss
|
40
43
|
- Les Hill
|
@@ -46,6 +49,7 @@ Resque Scheduler authors
|
|
46
49
|
- Michael Lovitt
|
47
50
|
- Michael Nikitochkin
|
48
51
|
- Michael Rykov
|
52
|
+
- Mike MacDonald
|
49
53
|
- Nickolas Means
|
50
54
|
- Olek Janiszewski
|
51
55
|
- Olivier Brisse
|
@@ -59,11 +63,13 @@ Resque Scheduler authors
|
|
59
63
|
- Scott Francis
|
60
64
|
- Sean Stephens
|
61
65
|
- Sebastian Kippe
|
66
|
+
- Sharang Dashputre
|
62
67
|
- Spring MC
|
63
68
|
- tbprojects
|
64
69
|
- Tim Liner
|
65
70
|
- Tony Lewis
|
66
71
|
- Tom Crayford
|
72
|
+
- Tsu-Shiuan Lin
|
67
73
|
- Vincent Zhu
|
68
74
|
- Vladislav Shub
|
69
75
|
- V Sreekanth
|
@@ -79,3 +85,4 @@ Resque Scheduler authors
|
|
79
85
|
- malomalo
|
80
86
|
- sawanoboly
|
81
87
|
- serek
|
88
|
+
- iloveitaly
|
data/CHANGELOG.md
CHANGED
@@ -2,7 +2,42 @@
|
|
2
2
|
|
3
3
|
**ATTN**: This project uses [semantic versioning](http://semver.org/).
|
4
4
|
|
5
|
-
##
|
5
|
+
## Unreleased
|
6
|
+
|
7
|
+
## [4.5.0]
|
8
|
+
### Added
|
9
|
+
- Support Ruby 3
|
10
|
+
- Add optional argument to `remove_schedule` to control reloading of the schedule
|
11
|
+
|
12
|
+
### Fixed
|
13
|
+
- Fix XSS vulnerability on the `/delayed/search` page
|
14
|
+
- Ensure that jobs are directly created for jobs enqueued at `Time.now`
|
15
|
+
- Fix queuing to custom job queues in `enqueue_delayed_selection`
|
16
|
+
- Ensure `before_enqueue` and `after_enqueue` callbacks are called in all cases of queuing a job
|
17
|
+
- Fix redis error when running resque-scheduler without Redis
|
18
|
+
|
19
|
+
### Changed
|
20
|
+
- Change CI from Travis to GitHub Actions
|
21
|
+
- Only allow rufus-scheduler versions lower than 3.7
|
22
|
+
- Update vagrant configuration
|
23
|
+
|
24
|
+
## [4.4.0] - 2019-04-11
|
25
|
+
### Added
|
26
|
+
- Support Resque 2
|
27
|
+
- Support redis-rb 4
|
28
|
+
- Support Ruby 2.5
|
29
|
+
|
30
|
+
### Fixed
|
31
|
+
- Redis timeouts no longer crash the scheduler process
|
32
|
+
- Fix race condition when running multiple schedulers
|
33
|
+
- Fix setting the `poll_sleep_amount` option
|
34
|
+
- Escape class names in resque-web /delayed URLs
|
35
|
+
|
36
|
+
### Changed
|
37
|
+
- Addressed redis-namespace deprecation warnings
|
38
|
+
- Ensure `enqueue_in` args are Numeric, catching a common issue passing `ActiveSupport::Duration`
|
39
|
+
|
40
|
+
## [4.3.1] - 2017-11-20
|
6
41
|
### Changed
|
7
42
|
- Add support and testing for ruby 2.4
|
8
43
|
- Change log format and file name
|
@@ -11,6 +46,7 @@
|
|
11
46
|
|
12
47
|
### Fixed
|
13
48
|
- Reporting version via `resque-scheduler --version`
|
49
|
+
- Class name escaping in `/delayed` view
|
14
50
|
|
15
51
|
## [4.3.0] - 2016-06-26
|
16
52
|
### Added
|
@@ -407,7 +443,9 @@
|
|
407
443
|
### Added
|
408
444
|
- Initial release
|
409
445
|
|
410
|
-
[Unreleased]: https://github.com/resque/resque-scheduler/compare/v4.
|
446
|
+
[Unreleased]: https://github.com/resque/resque-scheduler/compare/v4.4.0...HEAD
|
447
|
+
[4.4.0]: https://github.com/resque/resque-scheduler/compare/v4.3.1...v4.4.0
|
448
|
+
[4.3.1]: https://github.com/resque/resque-scheduler/compare/v4.3.0...v4.3.1
|
411
449
|
[4.3.0]: https://github.com/resque/resque-scheduler/compare/v4.2.1...v4.3.0
|
412
450
|
[4.2.1]: https://github.com/resque/resque-scheduler/compare/v4.2.0...v4.2.1
|
413
451
|
[4.2.0]: https://github.com/resque/resque-scheduler/compare/v4.1.0...v4.2.0
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -2,10 +2,8 @@ resque-scheduler
|
|
2
2
|
================
|
3
3
|
|
4
4
|
|
5
|
-
[![Dependency Status](https://gemnasium.com/badges/github.com/resque/resque-scheduler.svg)](https://gemnasium.com/github.com/resque/resque-scheduler)
|
6
5
|
[![Gem Version](https://badge.fury.io/rb/resque-scheduler.svg)](https://badge.fury.io/rb/resque-scheduler)
|
7
|
-
[![
|
8
|
-
[![Windows Build Status](https://ci.appveyor.com/api/projects/status/sxvf2086v5j0absb/branch/master?svg=true)](https://ci.appveyor.com/project/resque/resque-scheduler/branch/master)
|
6
|
+
[![Ruby specs](https://github.com/resque/resque-scheduler/actions/workflows/ruby.yml/badge.svg)](https://github.com/resque/resque-scheduler/actions)
|
9
7
|
[![Code Climate](https://codeclimate.com/github/resque/resque-scheduler/badges/gpa.svg)](https://codeclimate.com/github/resque/resque-scheduler)
|
10
8
|
|
11
9
|
### Description
|
@@ -13,7 +11,7 @@ resque-scheduler
|
|
13
11
|
Resque-scheduler is an extension to [Resque](http://github.com/resque/resque)
|
14
12
|
that adds support for queueing items in the future.
|
15
13
|
|
16
|
-
Job scheduling is supported in two different
|
14
|
+
Job scheduling is supported in two different ways: Recurring (scheduled) and
|
17
15
|
Delayed.
|
18
16
|
|
19
17
|
Scheduled jobs are like cron jobs, recurring on a regular basis. Delayed
|
@@ -160,7 +158,7 @@ following task to wherever tasks are kept, such as
|
|
160
158
|
```ruby
|
161
159
|
task 'resque:pool:setup' do
|
162
160
|
Resque::Pool.after_prefork do |job|
|
163
|
-
Resque.redis.
|
161
|
+
Resque.redis._client.reconnect
|
164
162
|
end
|
165
163
|
end
|
166
164
|
```
|
@@ -235,6 +233,17 @@ Resque.remove_delayed_selection { |args| args[0]['account_id'] == current_accoun
|
|
235
233
|
Resque.remove_delayed_selection { |args| args[0]['user_id'] == current_user.id }
|
236
234
|
```
|
237
235
|
|
236
|
+
If you need to cancel a delayed job based on some matching arguments AND by which class the job is, but don't wish to specify each argument from when the job was created, you can do like so:
|
237
|
+
|
238
|
+
``` ruby
|
239
|
+
# after you've enqueued a job like:
|
240
|
+
Resque.enqueue_at(5.days.from_now, SendFollowUpEmail, :account_id => current_account.id, :user_id => current_user.id)
|
241
|
+
# remove jobs matching just the account and that were of the class SendFollowUpEmail:
|
242
|
+
Resque.remove_delayed_selection(SendFollowUpEmail) { |args| args[0]['account_id'] == current_account.id }
|
243
|
+
# or remove jobs matching just the user and that were of the class SendFollowUpEmail:
|
244
|
+
Resque.remove_delayed_selection(SendFollowUpEmail) { |args| args[0]['user_id'] == current_user.id }
|
245
|
+
```
|
246
|
+
|
238
247
|
If you need to enqueue immediately a delayed job based on some matching arguments, but don't wish to specify each argument from when the job was created, you can do like so:
|
239
248
|
|
240
249
|
``` ruby
|
@@ -338,8 +347,8 @@ for handling the heavy lifting of the actual scheduling engine.
|
|
338
347
|
#### Dynamic schedules
|
339
348
|
|
340
349
|
Dynamic schedules are programmatically set on a running `resque-scheduler`.
|
341
|
-
|
342
|
-
when setting schedules.
|
350
|
+
Most [rufus-scheduler](http://github.com/jmettraux/rufus-scheduler) options are supported
|
351
|
+
when setting schedules. Specifically the `overlap` option will not work.
|
343
352
|
|
344
353
|
Dynamic schedules are not enabled by default. To be able to dynamically set schedules, you
|
345
354
|
must pass the following to `resque-scheduler` initialization (see *Installation* above for a more complete example):
|
@@ -516,7 +525,7 @@ RESQUE_SCHEDULER_MASTER_LOCK_PREFIX=MyApp: rake resque:scheduler
|
|
516
525
|
|
517
526
|
### resque-web Additions
|
518
527
|
|
519
|
-
Resque-scheduler also adds
|
528
|
+
Resque-scheduler also adds two tabs to the resque-web UI. One is for viewing
|
520
529
|
(and manually queueing) the schedule and one is for viewing pending jobs in
|
521
530
|
the delayed queue.
|
522
531
|
|
@@ -550,11 +559,7 @@ require 'resque/scheduler/server'
|
|
550
559
|
|
551
560
|
That should make the scheduler tabs show up in `resque-web`.
|
552
561
|
|
553
|
-
|
554
|
-
|
555
|
-
As of resque-scheduler 2.0.0, it's no longer necessary to have the resque-web
|
556
|
-
process aware of the schedule because it reads it from redis. But prior to
|
557
|
-
2.0, you'll want to make sure you load the schedule in this file as well.
|
562
|
+
You'll want to make sure you load the schedule in this file as well.
|
558
563
|
Something like this:
|
559
564
|
|
560
565
|
```ruby
|
@@ -634,7 +639,7 @@ that happens on Travis CI and Appveyor:
|
|
634
639
|
bundle install
|
635
640
|
|
636
641
|
# Make sure tests are green before you change stuff
|
637
|
-
bundle exec rake
|
642
|
+
bundle exec rubocop && bundle exec rake
|
638
643
|
# Change stuff
|
639
644
|
# Repeat
|
640
645
|
```
|
data/Rakefile
CHANGED
@@ -1,13 +1,9 @@
|
|
1
1
|
# vim:fileencoding=utf-8
|
2
2
|
require 'bundler/gem_tasks'
|
3
3
|
require 'rake/testtask'
|
4
|
-
require 'rubocop/rake_task'
|
5
4
|
require 'yard'
|
6
5
|
|
7
|
-
task default:
|
8
|
-
task default: [:test] if RUBY_PLATFORM =~ /java/
|
9
|
-
|
10
|
-
RuboCop::RakeTask.new
|
6
|
+
task default: :test
|
11
7
|
|
12
8
|
Rake::TestTask.new do |t|
|
13
9
|
t.libs << 'test'
|
@@ -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,17 @@ 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
|
|
60
66
|
# 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
|
67
|
+
# +timestamp+ can be either in seconds or a datetime object. The
|
68
|
+
# insertion time complexity is O(log(n)). Returns true if it's
|
69
|
+
# the first job to be scheduled at that time, else false.
|
64
70
|
def delayed_push(timestamp, item)
|
65
71
|
# First add this item to the list for this timestamp
|
66
72
|
redis.rpush("delayed:#{timestamp.to_i}", encode(item))
|
@@ -82,6 +88,7 @@ module Resque
|
|
82
88
|
end
|
83
89
|
|
84
90
|
# Returns the size of the delayed queue schedule
|
91
|
+
# this does not represent the number of items in the queue to be scheduled
|
85
92
|
def delayed_queue_schedule_size
|
86
93
|
redis.zcard :delayed_queue_schedule
|
87
94
|
end
|
@@ -143,6 +150,11 @@ module Resque
|
|
143
150
|
remove_delayed_job(search)
|
144
151
|
end
|
145
152
|
|
153
|
+
def remove_delayed_in_queue(klass, queue, *args)
|
154
|
+
search = encode(job_to_hash_with_queue(queue, klass, args))
|
155
|
+
remove_delayed_job(search)
|
156
|
+
end
|
157
|
+
|
146
158
|
# Given an encoded item, enqueue it now
|
147
159
|
def enqueue_delayed(klass, *args)
|
148
160
|
hash = job_to_hash(klass, args)
|
@@ -151,6 +163,13 @@ module Resque
|
|
151
163
|
end
|
152
164
|
end
|
153
165
|
|
166
|
+
def enqueue_delayed_with_queue(klass, queue, *args)
|
167
|
+
hash = job_to_hash_with_queue(queue, klass, args)
|
168
|
+
remove_delayed_in_queue(klass, queue, *args).times do
|
169
|
+
Resque::Scheduler.enqueue_from_config(hash)
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
154
173
|
# Given a block, remove jobs that return true from a block
|
155
174
|
#
|
156
175
|
# This allows for removal of delayed jobs that have arguments matching
|
@@ -175,7 +194,15 @@ module Resque
|
|
175
194
|
found_jobs.reduce(0) do |sum, encoded_job|
|
176
195
|
decoded_job = decode(encoded_job)
|
177
196
|
klass = Util.constantize(decoded_job['class'])
|
178
|
-
|
197
|
+
queue = decoded_job['queue']
|
198
|
+
|
199
|
+
if queue
|
200
|
+
jobs_queued = enqueue_delayed_with_queue(klass, queue, *decoded_job['args'])
|
201
|
+
else
|
202
|
+
jobs_queued = enqueue_delayed(klass, *decoded_job['args'])
|
203
|
+
end
|
204
|
+
|
205
|
+
jobs_queued + sum
|
179
206
|
end
|
180
207
|
end
|
181
208
|
|
@@ -265,6 +292,8 @@ module Resque
|
|
265
292
|
{ class: klass.to_s, args: args, queue: queue }
|
266
293
|
end
|
267
294
|
|
295
|
+
# Removes a job from the queue, but not modify the timestamp schedule. This method
|
296
|
+
# will not effect the output of `delayed_queue_schedule_size`
|
268
297
|
def remove_delayed_job(encoded_job)
|
269
298
|
return 0 if Resque.inline?
|
270
299
|
|
@@ -277,6 +306,9 @@ module Resque
|
|
277
306
|
end
|
278
307
|
end
|
279
308
|
|
309
|
+
# timestamp key is not removed from the schedule, this is done later
|
310
|
+
# by the scheduler loop
|
311
|
+
|
280
312
|
return 0 if replies.nil? || replies.empty?
|
281
313
|
replies.each_slice(2).map(&:first).inject(:+)
|
282
314
|
end
|
data/lib/resque/scheduler/env.rb
CHANGED
@@ -43,7 +43,7 @@ module Resque
|
|
43
43
|
end
|
44
44
|
|
45
45
|
Process.daemon(true, !Resque::Scheduler.quiet)
|
46
|
-
Resque.redis.
|
46
|
+
Resque.redis._client.reconnect
|
47
47
|
end
|
48
48
|
|
49
49
|
def setup_pid_file
|
@@ -64,13 +64,13 @@ module Resque
|
|
64
64
|
|
65
65
|
c.dynamic = !!options[:dynamic] if options.key?(:dynamic)
|
66
66
|
|
67
|
-
c.env = options[:env] if options.key(:env)
|
67
|
+
c.env = options[:env] if options.key?(:env)
|
68
68
|
|
69
69
|
c.logfile = options[:logfile] if options.key?(:logfile)
|
70
70
|
|
71
71
|
c.logformat = options[:logformat] if options.key?(:logformat)
|
72
72
|
|
73
|
-
if psleep = options[:poll_sleep_amount] && !psleep.nil?
|
73
|
+
if (psleep = options[:poll_sleep_amount]) && !psleep.nil?
|
74
74
|
c.poll_sleep_amount = Float(psleep)
|
75
75
|
end
|
76
76
|
|
@@ -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})
|
@@ -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
|
@@ -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>
|
@@ -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 = []
|
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
|
@@ -420,10 +428,10 @@ module Resque
|
|
420
428
|
private
|
421
429
|
|
422
430
|
def enqueue_recurring(name, config)
|
423
|
-
if
|
431
|
+
if am_master
|
424
432
|
log! "queueing #{config['class']} (#{name})"
|
425
|
-
Resque.last_enqueued_at(name, Time.now.to_s)
|
426
433
|
enqueue(config)
|
434
|
+
Resque.last_enqueued_at(name, Time.now.to_s)
|
427
435
|
end
|
428
436
|
end
|
429
437
|
|
@@ -442,6 +450,11 @@ module Resque
|
|
442
450
|
def internal_name
|
443
451
|
"resque-scheduler-#{Resque::Scheduler::VERSION}"
|
444
452
|
end
|
453
|
+
|
454
|
+
def am_master
|
455
|
+
@am_master = master? unless defined?(@am_master)
|
456
|
+
@am_master
|
457
|
+
end
|
445
458
|
end
|
446
459
|
end
|
447
460
|
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
|
@@ -29,7 +31,7 @@ Gem::Specification.new do |spec|
|
|
29
31
|
|
30
32
|
spec.files = `git ls-files -z`.split("\0").reject do |f|
|
31
33
|
f.match(%r{^(test|spec|features|examples|bin|tasks)/}) ||
|
32
|
-
f.match(/^(Vagrantfile|Gemfile\.lock
|
34
|
+
f.match(/^(Vagrantfile|Gemfile\.lock)/) ||
|
33
35
|
f.match(/^\.(rubocop|simplecov|travis|vagrant|gitignore)/)
|
34
36
|
end
|
35
37
|
spec.bindir = 'exe'
|
@@ -48,13 +50,15 @@ Gem::Specification.new do |spec|
|
|
48
50
|
spec.add_development_dependency 'test-unit'
|
49
51
|
spec.add_development_dependency 'yard'
|
50
52
|
spec.add_development_dependency 'tzinfo-data'
|
53
|
+
spec.add_development_dependency 'timecop'
|
51
54
|
|
52
55
|
# We pin rubocop because new cops have a tendency to result in false-y
|
53
56
|
# positives for new contributors, which is not a nice experience.
|
54
57
|
spec.add_development_dependency 'rubocop', '~> 0.40.0'
|
55
58
|
|
56
59
|
spec.add_runtime_dependency 'mono_logger', '~> 1.0'
|
57
|
-
spec.add_runtime_dependency 'redis', '>= 3.3'
|
58
|
-
spec.add_runtime_dependency 'resque', '
|
59
|
-
|
60
|
+
spec.add_runtime_dependency 'redis', '>= 3.3'
|
61
|
+
spec.add_runtime_dependency 'resque', '>= 1.27'
|
62
|
+
# rufus-scheduler v3.7 causes a failure in test/multi_process_test.rb
|
63
|
+
spec.add_runtime_dependency 'rufus-scheduler', '~> 3.2', '< 3.7'
|
60
64
|
end
|
metadata
CHANGED
@@ -1,17 +1,18 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: resque-scheduler
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.
|
4
|
+
version: 4.5.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
|
-
|
11
|
+
- Michael Bianco
|
12
|
+
autorequire:
|
12
13
|
bindir: exe
|
13
14
|
cert_chain: []
|
14
|
-
date:
|
15
|
+
date: 2021-09-28 00:00:00.000000000 Z
|
15
16
|
dependencies:
|
16
17
|
- !ruby/object:Gem::Dependency
|
17
18
|
name: bundler
|
@@ -181,6 +182,20 @@ dependencies:
|
|
181
182
|
- - ">="
|
182
183
|
- !ruby/object:Gem::Version
|
183
184
|
version: '0'
|
185
|
+
- !ruby/object:Gem::Dependency
|
186
|
+
name: timecop
|
187
|
+
requirement: !ruby/object:Gem::Requirement
|
188
|
+
requirements:
|
189
|
+
- - ">="
|
190
|
+
- !ruby/object:Gem::Version
|
191
|
+
version: '0'
|
192
|
+
type: :development
|
193
|
+
prerelease: false
|
194
|
+
version_requirements: !ruby/object:Gem::Requirement
|
195
|
+
requirements:
|
196
|
+
- - ">="
|
197
|
+
- !ruby/object:Gem::Version
|
198
|
+
version: '0'
|
184
199
|
- !ruby/object:Gem::Dependency
|
185
200
|
name: rubocop
|
186
201
|
requirement: !ruby/object:Gem::Requirement
|
@@ -216,9 +231,6 @@ dependencies:
|
|
216
231
|
- - ">="
|
217
232
|
- !ruby/object:Gem::Version
|
218
233
|
version: '3.3'
|
219
|
-
- - "<"
|
220
|
-
- !ruby/object:Gem::Version
|
221
|
-
version: '5'
|
222
234
|
type: :runtime
|
223
235
|
prerelease: false
|
224
236
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -226,23 +238,20 @@ dependencies:
|
|
226
238
|
- - ">="
|
227
239
|
- !ruby/object:Gem::Version
|
228
240
|
version: '3.3'
|
229
|
-
- - "<"
|
230
|
-
- !ruby/object:Gem::Version
|
231
|
-
version: '5'
|
232
241
|
- !ruby/object:Gem::Dependency
|
233
242
|
name: resque
|
234
243
|
requirement: !ruby/object:Gem::Requirement
|
235
244
|
requirements:
|
236
|
-
- - "
|
245
|
+
- - ">="
|
237
246
|
- !ruby/object:Gem::Version
|
238
|
-
version: '1.
|
247
|
+
version: '1.27'
|
239
248
|
type: :runtime
|
240
249
|
prerelease: false
|
241
250
|
version_requirements: !ruby/object:Gem::Requirement
|
242
251
|
requirements:
|
243
|
-
- - "
|
252
|
+
- - ">="
|
244
253
|
- !ruby/object:Gem::Version
|
245
|
-
version: '1.
|
254
|
+
version: '1.27'
|
246
255
|
- !ruby/object:Gem::Dependency
|
247
256
|
name: rufus-scheduler
|
248
257
|
requirement: !ruby/object:Gem::Requirement
|
@@ -250,6 +259,9 @@ dependencies:
|
|
250
259
|
- - "~>"
|
251
260
|
- !ruby/object:Gem::Version
|
252
261
|
version: '3.2'
|
262
|
+
- - "<"
|
263
|
+
- !ruby/object:Gem::Version
|
264
|
+
version: '3.7'
|
253
265
|
type: :runtime
|
254
266
|
prerelease: false
|
255
267
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -257,6 +269,9 @@ dependencies:
|
|
257
269
|
- - "~>"
|
258
270
|
- !ruby/object:Gem::Version
|
259
271
|
version: '3.2'
|
272
|
+
- - "<"
|
273
|
+
- !ruby/object:Gem::Version
|
274
|
+
version: '3.7'
|
260
275
|
description: |2
|
261
276
|
Light weight job scheduling on top of Resque.
|
262
277
|
Adds methods enqueue_at/enqueue_in to schedule jobs in the future.
|
@@ -266,11 +281,15 @@ email:
|
|
266
281
|
- sirup@sirupsen.com
|
267
282
|
- ryan@yaauie.com
|
268
283
|
- dan@meatballhat.com
|
284
|
+
- mike@mikebian.co
|
269
285
|
executables:
|
270
286
|
- resque-scheduler
|
271
287
|
extensions: []
|
272
288
|
extra_rdoc_files: []
|
273
289
|
files:
|
290
|
+
- ".github/dependabot.yml"
|
291
|
+
- ".github/workflows/rubocop.yml"
|
292
|
+
- ".github/workflows/ruby.yml"
|
274
293
|
- AUTHORS.md
|
275
294
|
- CHANGELOG.md
|
276
295
|
- CODE_OF_CONDUCT.md
|
@@ -313,7 +332,7 @@ homepage: http://github.com/resque/resque-scheduler
|
|
313
332
|
licenses:
|
314
333
|
- MIT
|
315
334
|
metadata: {}
|
316
|
-
post_install_message:
|
335
|
+
post_install_message:
|
317
336
|
rdoc_options: []
|
318
337
|
require_paths:
|
319
338
|
- lib
|
@@ -328,9 +347,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
328
347
|
- !ruby/object:Gem::Version
|
329
348
|
version: '0'
|
330
349
|
requirements: []
|
331
|
-
|
332
|
-
|
333
|
-
signing_key:
|
350
|
+
rubygems_version: 3.1.6
|
351
|
+
signing_key:
|
334
352
|
specification_version: 4
|
335
353
|
summary: Light weight job scheduling on top of Resque
|
336
354
|
test_files: []
|