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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 52d400f5dbdd7e1d642466e7999f6ec7f6805355
4
- data.tar.gz: 7caa30cc7095a5451f915a981b64cd0dda7149e5
2
+ SHA256:
3
+ metadata.gz: 2c97d0ecaec5a456e20e91d98779f7792fafd99e09f1bfd85452234a01ba47c0
4
+ data.tar.gz: f3947f2446b6ddac4d5555d467a302a3032a08d3dd77bdc039253674f70a85e1
5
5
  SHA512:
6
- metadata.gz: 20630b816c225504beb88315ef1df2fa1672e44e05c6386446c53e6b5422ab7b1cf478775f6660e7f880a73771f073746fb0853258a5ad71f450b51e15290ce2
7
- data.tar.gz: 8fa83bedc4ffd9759d5390ad19ce82b8188445df3aa5c46ac2a32dc8a162e66c69c73f4599ad90ea4a3eb2191661fe82ece5aea30bd834d3e9e8495267e84a7b
6
+ metadata.gz: cbfefeb510538682d188284280ca56af1641de3dde1a63ad8b79b5a09dcc916dc902839782a9ad988421c77b84146a05b4077291aa754e24d07dc75440786c2e
7
+ data.tar.gz: 955193ba760e37bd6f58f94a4ba67edab755329a68e4deefa0466c822d3fbd3d057cf357a410bedf23fd145b687255b3fe783d44890d7d4dfd0307773c1baeb5
@@ -0,0 +1,12 @@
1
+ version: 2
2
+
3
+ updates:
4
+ - package-ecosystem: "github-actions"
5
+ directory: "/"
6
+ schedule:
7
+ interval: "weekly"
8
+
9
+ - package-ecosystem: "bundler"
10
+ directory: "/"
11
+ schedule:
12
+ interval: "weekly"
@@ -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
- ## [Unreleased]
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.3.0...HEAD
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
@@ -1,4 +1,12 @@
1
1
  # vim:fileencoding=utf-8
2
2
  source 'https://rubygems.org'
3
3
 
4
+ case req = ENV['RESQUE']
5
+ when nil
6
+ when 'master'
7
+ gem 'resque', git: 'https://github.com/resque/resque'
8
+ else
9
+ gem 'resque', req
10
+ end
11
+
4
12
  gemspec
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
- [![Build Status](https://travis-ci.org/resque/resque-scheduler.svg?branch=master)](https://travis-ci.org/resque/resque-scheduler)
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 way: Recurring (scheduled) and
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.client.reconnect
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
- All [rufus-scheduler](http://github.com/jmettraux/rufus-scheduler) options are supported
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 to tabs to the resque-web UI. One is for viewing
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
- #### Changes as of 2.0.0
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: [:rubocop, :test] unless RUBY_PLATFORM =~ /java/
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 < Time.now.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::Job.create(queue, klass, *args)
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 Insertion
62
- # if O(log(n)). Returns true if it's the first job to be scheduled at
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
- sum + enqueue_delayed(klass, *decoded_job['args'])
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
@@ -43,7 +43,7 @@ module Resque
43
43
  end
44
44
 
45
45
  Process.daemon(true, !Resque::Scheduler.quiet)
46
- Resque.redis.client.reconnect
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 Errno::EAGAIN, Errno::ECONNRESET, Redis::CannotConnectError
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
- # :rails_envs is the list of envs where the job gets loaded. Envs are
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
- def remove_schedule(name)
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=" + URI.encode(job['args'].to_json)) %>">All schedules</a>
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>
@@ -1,5 +1,5 @@
1
1
  <form method="POST" action="<%= u 'delayed/search' %>">
2
- <input type='input' name='search' value="<%= params[:search] %>"/>
2
+ <input type='input' name='search' value="<%= h params[:search] %>"/>
3
3
  <input type='submit' value='Search'/>
4
4
  </form>
5
5
 
@@ -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(URI.decode(params[:args]))
90
+ @args = JSON.load(CGI.unescape(params[:args]))
91
91
  @timestamps = Resque.scheduled_at(klass, *@args)
92
92
  rescue
93
93
  @timestamps = []
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Resque
4
4
  module Scheduler
5
- VERSION = '4.3.1'.freeze
5
+ VERSION = '4.5.0'.freeze
6
6
  end
7
7
  end
@@ -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
- # Load the schedule into rufus
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
- if master?
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
- rescue Errno::EAGAIN, Errno::ECONNRESET, Redis::CannotConnectError => e
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 master?
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 master?
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
@@ -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|appveyor\.yml)/) ||
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', '< 5'
58
- spec.add_runtime_dependency 'resque', '~> 1.26'
59
- spec.add_runtime_dependency 'rufus-scheduler', '~> 3.2'
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.3.1
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
- autorequire:
11
+ - Michael Bianco
12
+ autorequire:
12
13
  bindir: exe
13
14
  cert_chain: []
14
- date: 2017-11-20 00:00:00.000000000 Z
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.26'
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.26'
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
- rubyforge_project:
332
- rubygems_version: 2.6.8
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: []