resque-scheduler 4.6.0 → 4.10.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cf266ccd935c9464051349f32169248c7fab52aa84304a98f0d05e5e91ccec22
4
- data.tar.gz: 517e84a33953fa3bf695ae26f23912d436fc86b7dc0ac9502fb09ca1cc02f1c3
3
+ metadata.gz: 6cf8e385c64ab6efafcc8f3a499ec2dc8d7be736604e7d4578dd356f1c19d6e9
4
+ data.tar.gz: a564652590bf3c5dc85695cbbb57fb4ca85873de78c94f0580a104ef5d98cf55
5
5
  SHA512:
6
- metadata.gz: 91b8916a16ad2a6a20860001f137fb558d6dbfa7aca3c67abb022acc298a3f2afac7c1527a043b2d5ed3fa582d0203cc988b101cc45819ae3832145328cdea7d
7
- data.tar.gz: 90669eb2a75e71612b1505c87a6ed704e70b80b34aa89023ce84e8a256c1d3e0e4eb2a7931c8e480ff99524ed489bb97ed2d98f512f6646f19d50751613ac97c
6
+ metadata.gz: 2ab0cea69751963f68055eae115c349a885439a5b33c1c3046a5abd4fc30b676233964d430fa5aeb3eb7960d9339772d41ca31c575156eb4e6583cc66de7497e
7
+ data.tar.gz: f0a4ab726ea640f9df76bbb824078252fb90de9d40c90220611c71069363025933f4a97200c73c13c7c91ff4f02a8c64c735372bbd2e0510e4e5bd021ec081fb
@@ -27,7 +27,7 @@ jobs:
27
27
 
28
28
  steps:
29
29
  - name: Checkout repository
30
- uses: actions/checkout@v3
30
+ uses: actions/checkout@v4
31
31
 
32
32
  # Initializes the CodeQL tools for scanning.
33
33
  - name: Initialize CodeQL
@@ -14,11 +14,11 @@ jobs:
14
14
  matrix:
15
15
  os: [ubuntu-latest]
16
16
  ruby: [
17
- 2.4
17
+ 2.7
18
18
  ]
19
19
 
20
20
  steps:
21
- - uses: actions/checkout@v3
21
+ - uses: actions/checkout@v4
22
22
  - uses: ruby/setup-ruby@v1
23
23
  with:
24
24
  ruby-version: ${{ matrix.ruby }}
@@ -26,38 +26,53 @@ jobs:
26
26
  - 2.7
27
27
  - "3.0"
28
28
  - 3.1
29
+ - 3.2
29
30
  resque-version:
30
31
  - "master"
31
- - "~> 2.2.0"
32
+ - "~> 2.4.0"
32
33
  - "~> 1.27"
33
34
  rufus-scheduler:
34
35
  - "3.2"
35
36
  - "3.4"
36
37
  - "3.5"
37
38
  - "3.6"
39
+ redis-version:
40
+ - "~> 4.x"
41
+ - "~> 5.x"
38
42
  exclude:
39
43
  - ruby-version: head
40
44
  rufus-scheduler: 3.2
45
+ - ruby-version: 3.2
46
+ rufus-scheduler: 3.2
41
47
 
42
48
  - ruby-version: 2.3
43
- resque-version: 1.27
49
+ resque-version: "~> 1.27"
44
50
  rufus-scheduler: 3.4
45
51
  - ruby-version: 2.3
46
- resque-version: 1.27
52
+ resque-version: "~> 1.27"
47
53
  rufus-scheduler: 3.5
48
54
  - ruby-version: 2.5
49
- resque-version: 2.2.0
55
+ resque-version: "~> 2.4.0"
50
56
  rufus-scheduler: 3.5
51
57
  - ruby-version: 2.5
52
58
  resque-version: master
53
59
  rufus-scheduler: 3.2
60
+
61
+ - ruby-version: 2.3
62
+ redis-version: "~> 5.x"
63
+ - ruby-version: 2.4
64
+ redis-version: "~> 5.x"
65
+
66
+ - resque-version: "~> 1.27"
67
+ redis-version: "~> 5.x"
54
68
  env:
69
+ REDIS_VERSION: "${{ matrix.redis-version }}"
55
70
  RESQUE: "${{ matrix.resque-version }}"
56
71
  RUFUS_SCHEDULER: "${{ matrix.rufus-scheduler }}"
57
72
  COVERAGE: 1
58
73
 
59
74
  steps:
60
- - uses: actions/checkout@v3
75
+ - uses: actions/checkout@v4
61
76
  - uses: ruby/setup-ruby@v1
62
77
  with:
63
78
  ruby-version: "${{ matrix.ruby-version }}"
data/AUTHORS.md CHANGED
@@ -29,6 +29,7 @@ Resque Scheduler authors
29
29
  - Henrik Nyh
30
30
  - Hormoz Kheradmand
31
31
  - Ian Davies
32
+ - Irving Reid
32
33
  - James Le Cuirot
33
34
  - Jarkko Mönkkönen
34
35
  - Jimmy Chao
@@ -87,4 +88,5 @@ Resque Scheduler authors
87
88
  - malomalo
88
89
  - sawanoboly
89
90
  - serek
90
- - iloveitaly
91
+ - iloveitaly
92
+ - treacher
data/CHANGELOG.md CHANGED
@@ -2,6 +2,41 @@
2
2
 
3
3
  **ATTN**: This project uses [semantic versioning](http://semver.org/).
4
4
 
5
+ ## [4.10.2] - 2023-12-15
6
+ ### Fixed
7
+ * Finish fixing CVE-2022-44303, XSS in delayed_schedules by @PatrickTulskie in #783
8
+
9
+ ## [4.10.1] - 2023-12-15
10
+ ### Fixed
11
+ * Fix json dump crasher with JSON 2.7.0+ by @PatrickTulskie in #781
12
+ * Fix for #761, reflected XSS in delayed_schedules.erb by @PatrickTulskie in #780
13
+
14
+ ## [4.10.0] - 2023-08-20
15
+ ### Added
16
+ * Add logfmt option for logging output (#763)
17
+
18
+ ### Fixed
19
+ * Rubocop Fixes (#771)
20
+
21
+ ## [4.9.0] - 2023-05-31
22
+ ### Changed
23
+ - Adding batching to re-queuing for timestamp by @brennen-stripe in #767
24
+ - Use non-deprecated form of Redis.sadd/srem by @irvingreid in #752
25
+ - Prompt for confirmation on 'Clear Delayed Jobs' by @mishina2228 in #754
26
+ - Address some deprecation warnings in the test suite and with srem/lrem pipelined usage by @PatrickTulskie in #770
27
+
28
+ ### Fixed
29
+ - Update CI matrix and fix tests by @mishina2228 in #766
30
+
31
+ ## [4.8.0] - 2023-27-1
32
+ - Replace deprecated Socket.gethostname with Addrinfo.getaddrinfo to fix deprecation warnings (#753)
33
+
34
+ ## [4.7.0] - 2022-10-6
35
+ ### Fixed
36
+ - Fix tests for redis-rb 5.0 (#757)
37
+ - Use Resque::DataStore#reconnect for redis-rb 5.0 compat (#757)
38
+ - Test suite runs `flushall` to prevent flakiness (#757)
39
+
5
40
  ## [4.6.0] - 2022-08-04
6
41
  ### Changed
7
42
  - Remove support for Ruby < 2.3
data/Gemfile CHANGED
@@ -15,4 +15,15 @@ else
15
15
  gem 'rufus-scheduler', rufus_scheduler_version
16
16
  end
17
17
 
18
+ case redis_version = ENV.fetch('REDIS_VERSION', 'latest')
19
+ when 'master'
20
+ gem 'redis', git: 'https://github.com/redis/redis-rb'
21
+ when 'latest'
22
+ gem 'redis'
23
+ else
24
+ gem 'redis', redis_version
25
+ end
26
+
27
+ gem 'sinatra', '> 2.0'
28
+
18
29
  gemspec
data/README.md CHANGED
@@ -139,7 +139,7 @@ requiring `resque` and `resque/scheduler` (default empty).
139
139
  * `RESQUE_SCHEDULER_INTERVAL` - Interval in seconds for checking if a
140
140
  scheduled job must run (coerced with `Kernel#Float()`) (default `5`)
141
141
  * `LOGFILE` - Log file name (default empty, meaning `$stdout`)
142
- * `LOGFORMAT` - Log output format to use (either `'text'` or `'json'`,
142
+ * `LOGFORMAT` - Log output format to use (either `'text'`, `'json'` or `'logfmt'`,
143
143
  default `'text'`)
144
144
  * `PIDFILE` - If non-empty, write process PID to file (default empty)
145
145
  * `QUIET` - Silence most output if non-empty (equivalent to a level of
@@ -158,7 +158,7 @@ following task to wherever tasks are kept, such as
158
158
  ```ruby
159
159
  task 'resque:pool:setup' do
160
160
  Resque::Pool.after_prefork do |job|
161
- Resque.redis._client.reconnect
161
+ Resque.redis.reconnect
162
162
  end
163
163
  end
164
164
  ```
@@ -663,7 +663,7 @@ are toggled by environment variables:
663
663
  - `QUIET` will stop logging anything. Completely silent.
664
664
  - `VERBOSE` opposite of 'QUIET'; will log even debug information
665
665
  - `LOGFILE` specifies the file to write logs to. (default standard output)
666
- - `LOGFORMAT` specifies either "text" or "json" output format
666
+ - `LOGFORMAT` specifies either "text", "json" or "logfmt" output format
667
667
  (default "text")
668
668
 
669
669
  All of these variables are optional and will be given the following default
@@ -44,7 +44,7 @@ module Resque
44
44
  @logfile ||= environment['LOGFILE']
45
45
  end
46
46
 
47
- # Sets whether to log in 'text' or 'json'
47
+ # Sets whether to log in 'text', 'json' or 'logfmt'
48
48
  attr_writer :logformat
49
49
 
50
50
  def logformat
@@ -65,6 +65,12 @@ module Resque
65
65
  @app_name ||= environment['APP_NAME']
66
66
  end
67
67
 
68
+ def delayed_requeue_batch_size
69
+ @delayed_requeue_batch_size ||= \
70
+ ENV['DELAYED_REQUEUE_BATCH_SIZE'].to_i if environment['DELAYED_REQUEUE_BATCH_SIZE']
71
+ @delayed_requeue_batch_size ||= 100
72
+ end
73
+
68
74
  # Amount of time in seconds to sleep between polls of the delayed
69
75
  # queue. Defaults to 5
70
76
  attr_writer :poll_sleep_amount
@@ -90,7 +90,7 @@ module Resque
90
90
  redis.rpush("delayed:#{timestamp.to_i}", encode(item))
91
91
 
92
92
  # Store the timestamps at with this item occurs
93
- redis.sadd("timestamps:#{encode(item)}", "delayed:#{timestamp.to_i}")
93
+ redis.sadd("timestamps:#{encode(item)}", ["delayed:#{timestamp.to_i}"])
94
94
 
95
95
  # Now, add this timestamp to the zsets. The score and the value are
96
96
  # the same since we'll be querying by timestamp, and we don't have
@@ -140,7 +140,7 @@ module Resque
140
140
  key = "delayed:#{timestamp.to_i}"
141
141
 
142
142
  encoded_item = redis.lpop(key)
143
- redis.srem("timestamps:#{encoded_item}", key)
143
+ redis.srem("timestamps:#{encoded_item}", [key])
144
144
  item = decode(encoded_item)
145
145
 
146
146
  # If the list is empty, remove it.
@@ -257,7 +257,7 @@ module Resque
257
257
  key = "delayed:#{timestamp.to_i}"
258
258
  encoded_job = encode(job_to_hash(klass, args))
259
259
 
260
- redis.srem("timestamps:#{encoded_job}", key)
260
+ redis.srem("timestamps:#{encoded_job}", [key])
261
261
  count = redis.lrem(key, 0, encoded_job)
262
262
  clean_up_timestamp(key, timestamp)
263
263
 
@@ -297,6 +297,22 @@ module Resque
297
297
  redis.hget('delayed:last_enqueued_at', job_name)
298
298
  end
299
299
 
300
+ def clean_up_timestamp(key, timestamp)
301
+ # Use a watch here to ensure nobody adds jobs to this delayed
302
+ # queue while we're removing it.
303
+ redis.watch(key) do
304
+ if redis.llen(key).to_i == 0
305
+ # If the list is empty, remove it.
306
+ redis.multi do |transaction|
307
+ transaction.del(key)
308
+ transaction.zrem(:delayed_queue_schedule, timestamp.to_i)
309
+ end
310
+ else
311
+ redis.redis.unwatch
312
+ end
313
+ end
314
+ end
315
+
300
316
  private
301
317
 
302
318
  def job_to_hash(klass, args)
@@ -317,7 +333,7 @@ module Resque
317
333
  replies = redis.pipelined do |pipeline|
318
334
  timestamps.each do |key|
319
335
  pipeline.lrem(key, 0, encoded_job)
320
- pipeline.srem("timestamps:#{encoded_job}", key)
336
+ pipeline.srem("timestamps:#{encoded_job}", [key])
321
337
  end
322
338
  end
323
339
 
@@ -328,22 +344,6 @@ module Resque
328
344
  replies.each_slice(2).map(&:first).inject(:+)
329
345
  end
330
346
 
331
- def clean_up_timestamp(key, timestamp)
332
- # Use a watch here to ensure nobody adds jobs to this delayed
333
- # queue while we're removing it.
334
- redis.watch(key) do
335
- if redis.llen(key).to_i == 0
336
- # If the list is empty, remove it.
337
- redis.multi do |transaction|
338
- transaction.del(key)
339
- transaction.zrem(:delayed_queue_schedule, timestamp.to_i)
340
- end
341
- else
342
- redis.redis.unwatch
343
- end
344
- end
345
- end
346
-
347
347
  def search_first_delayed_timestamp_in_range(start_at, stop_at)
348
348
  start_at = start_at.nil? ? '-inf' : start_at.to_i
349
349
  stop_at = stop_at.nil? ? '+inf' : stop_at.to_i
@@ -39,7 +39,7 @@ module Resque
39
39
  end
40
40
 
41
41
  Process.daemon(true, !Resque::Scheduler.quiet)
42
- Resque.redis._client.reconnect
42
+ Resque.redis.reconnect
43
43
  end
44
44
 
45
45
  def setup_pid_file
@@ -47,7 +47,7 @@ module Resque
47
47
 
48
48
  def hostname
49
49
  local_hostname = Socket.gethostname
50
- Socket.gethostbyname(local_hostname).first
50
+ Addrinfo.getaddrinfo(local_hostname, 'http').first.getnameinfo.first
51
51
  rescue
52
52
  local_hostname
53
53
  end
@@ -15,7 +15,7 @@ module Resque
15
15
  # - :quiet if logger needs to be silent for all levels. Default - false
16
16
  # - :verbose if there is a need in debug messages. Default - false
17
17
  # - :log_dev to output logs into a desired file. Default - STDOUT
18
- # - :format log format, either 'text' or 'json'. Default - 'text'
18
+ # - :format log format, either 'text', 'json' or 'logfmt'. Default - 'text'
19
19
  #
20
20
  # Example:
21
21
  #
@@ -32,6 +32,7 @@ module Resque
32
32
  # Returns an instance of MonoLogger
33
33
  def build
34
34
  logger = MonoLogger.new(@log_dev)
35
+ logger.progname = 'resque-scheduler'.freeze
35
36
  logger.level = level
36
37
  logger.formatter = send(:"#{@format}_formatter")
37
38
  logger
@@ -50,21 +51,31 @@ module Resque
50
51
  end
51
52
 
52
53
  def text_formatter
53
- proc do |severity, datetime, _progname, msg|
54
- "resque-scheduler: [#{severity}] #{datetime.iso8601}: #{msg}\n"
54
+ proc do |severity, datetime, progname, msg|
55
+ "#{progname}: [#{severity}] #{datetime.iso8601}: #{msg}\n"
55
56
  end
56
57
  end
57
58
 
58
59
  def json_formatter
59
60
  proc do |severity, datetime, progname, msg|
60
61
  require 'json'
61
- JSON.dump(
62
- name: 'resque-scheduler',
62
+ log_data = {
63
+ name: progname,
63
64
  progname: progname,
64
65
  level: severity,
65
66
  timestamp: datetime.iso8601,
66
67
  msg: msg
67
- ) + "\n"
68
+ }
69
+ JSON.dump(log_data) + "\n"
70
+ end
71
+ end
72
+
73
+ def logfmt_formatter
74
+ proc do |severity, datetime, progname, msg|
75
+ "timestamp=\"#{datetime.iso8601}\" " \
76
+ "level=\"#{severity}\" " \
77
+ "progname=\"#{progname}\" " \
78
+ "msg=\"#{msg}\"\n"
68
79
  end
69
80
  end
70
81
  end
@@ -91,7 +91,7 @@ module Resque
91
91
  non_persistent_schedules[name] = decode(encode(config))
92
92
  end
93
93
 
94
- redis.sadd(:schedules_changed, name)
94
+ redis.sadd(:schedules_changed, [name])
95
95
  reload_schedule! if reload
96
96
  end
97
97
 
@@ -105,7 +105,7 @@ module Resque
105
105
  def remove_schedule(name, reload = true)
106
106
  non_persistent_schedules.delete(name)
107
107
  redis.hdel(:persistent_schedules, name)
108
- redis.sadd(:schedules_changed, name)
108
+ redis.sadd(:schedules_changed, [name])
109
109
 
110
110
  reload_schedule! if reload
111
111
  end
@@ -16,6 +16,14 @@
16
16
  Showing <%= start = params[:start].to_i %> to <%= start + 20 %> of <b><%= size %></b> timestamps
17
17
  </p>
18
18
 
19
+ <% if size > 0 %>
20
+ <div style="padding-bottom: 10px">
21
+ <form method="POST" action="<%= u 'delayed/clear' %>" class='clear-delayed confirmSubmission'>
22
+ <input type='submit' name='' value='Clear Delayed Jobs' />
23
+ </form>
24
+ </div>
25
+ <% end %>
26
+
19
27
  <table>
20
28
  <tr>
21
29
  <th></th>
@@ -27,7 +35,7 @@
27
35
  </tr>
28
36
  <% resque.delayed_queue_peek(start, 20).each do |timestamp| %>
29
37
  <tr>
30
- <td>
38
+ <td style="padding-top: 12px; padding-bottom: 2px; width: 10px">
31
39
  <form action="<%= u "/delayed/queue_now" %>" method="post">
32
40
  <input type="hidden" name="timestamp" value="<%= timestamp.to_i %>">
33
41
  <input type="submit" value="Queue now">
@@ -53,11 +61,4 @@
53
61
  <% end %>
54
62
  </table>
55
63
 
56
- <% if size > 0 %>
57
- <br>
58
- <form method="POST" action="<%= u 'delayed/clear' %>" class='clear-delayed'>
59
- <input type='submit' name='' value='Clear Delayed Jobs' />
60
- </form>
61
- <% end %>
62
-
63
64
  <%= partial :next_more, :start => start, :size => size %>
@@ -1,4 +1,4 @@
1
- <h1>Delayed jobs scheduled for <%= params[:klass] %> (<%= show_job_arguments(@args) %>)</h1>
1
+ <h1>Delayed jobs scheduled for <%=h params[:klass] %> (<%=h show_job_arguments(@args) %>)</h1>
2
2
 
3
3
  <table class='jobs'>
4
4
  <tr>
@@ -13,13 +13,13 @@
13
13
  </tr>
14
14
  <% delayed.each do |job| %>
15
15
  <tr>
16
- <td>
16
+ <td style="padding-top: 12px; padding-bottom: 2px; width: 10px">
17
17
  <form action="<%= u "/delayed/queue_now" %>" method="post">
18
18
  <input type="hidden" name="timestamp" value="<%= job['timestamp'].to_i %>">
19
19
  <input type="submit" value="Queue now">
20
20
  </form>
21
21
  </td>
22
- <td>
22
+ <td style="padding-top: 12px; padding-bottom: 2px; width: 10px">
23
23
  <form action="<%= u "/delayed/cancel_now" %>" method="post">
24
24
  <input type="hidden" name="timestamp" value="<%= job['timestamp'].to_i %>">
25
25
  <input type="hidden" name="klass" value="<%= job['class'] %>">
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Resque
4
4
  module Scheduler
5
- VERSION = '4.6.0'.freeze
5
+ VERSION = '4.10.2'.freeze
6
6
  end
7
7
  end
@@ -206,16 +206,80 @@ module Resque
206
206
 
207
207
  # Enqueues all delayed jobs for a timestamp
208
208
  def enqueue_delayed_items_for_timestamp(timestamp)
209
- item = nil
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
+
210
215
  loop do
211
216
  handle_shutdown do
212
217
  # Continually check that it is still the master
213
- item = enqueue_next_item(timestamp) if am_master
218
+ if am_master
219
+ actual_batch_size = enqueue_items_in_batch_for_timestamp(timestamp,
220
+ batch_size)
221
+ end
214
222
  end
215
- # continue processing until there are no more ready items in this
216
- # timestamp
217
- break if item.nil?
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
218
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
219
283
  end
220
284
 
221
285
  def enqueue(config)
@@ -12,6 +12,7 @@ Gem::Specification.new do |spec|
12
12
  Ryan Biesemeyer
13
13
  Dan Buch
14
14
  Michael Bianco
15
+ Patrick Tulskie
15
16
  EOF
16
17
  spec.email = %w(
17
18
  bvandenbos@gmail.com
@@ -19,6 +20,7 @@ Gem::Specification.new do |spec|
19
20
  ryan@yaauie.com
20
21
  dan@meatballhat.com
21
22
  mike@mikebian.co
23
+ patricktulskie@gmail.com
22
24
  )
23
25
  spec.summary = 'Light weight job scheduling on top of Resque'
24
26
  spec.description = <<-DESCRIPTION
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: resque-scheduler
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.6.0
4
+ version: 4.10.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ben VandenBos
@@ -9,10 +9,11 @@ authors:
9
9
  - Ryan Biesemeyer
10
10
  - Dan Buch
11
11
  - Michael Bianco
12
+ - Patrick Tulskie
12
13
  autorequire:
13
14
  bindir: exe
14
15
  cert_chain: []
15
- date: 2022-08-20 00:00:00.000000000 Z
16
+ date: 2023-12-15 00:00:00.000000000 Z
16
17
  dependencies:
17
18
  - !ruby/object:Gem::Dependency
18
19
  name: bundler
@@ -254,6 +255,7 @@ email:
254
255
  - ryan@yaauie.com
255
256
  - dan@meatballhat.com
256
257
  - mike@mikebian.co
258
+ - patricktulskie@gmail.com
257
259
  executables:
258
260
  - resque-scheduler
259
261
  extensions: []
@@ -322,7 +324,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
322
324
  - !ruby/object:Gem::Version
323
325
  version: '0'
324
326
  requirements: []
325
- rubygems_version: 3.3.5
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