resque 2.7.0 → 3.0.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7419ce3cc8734b05527a47b0c5fb4a9eea0a5d33265a6e3214bb429980c37681
4
- data.tar.gz: 4216e18e121883e0350275e00c19e1d6c6f0965915d4b48a8a0a29f07e652317
3
+ metadata.gz: 357503e977394f513419b3146484eab796354a978d6d96e74e16fae0dc2fd3de
4
+ data.tar.gz: 4e3da6258793f0b094cba61c35436d30f1193d8d43553e312b8e5c14cbb7ee5b
5
5
  SHA512:
6
- metadata.gz: 7301e154b368d012161ae22d69cb8e4400977a3099392f7789369ca37b04a413d0abec092e60dd9dddee01bda81c55dbf182da5cede4a8c2beff94f8ed44bc94
7
- data.tar.gz: 85d0c05d98502b0da28ae60ca6117d3b4a47bbfc981b48c4168f6bf727bac8c4c325dcebf604f8916d0e04c97bf933651b6077b55ead117e7ecb1cc2cf4655f0
6
+ metadata.gz: 00e3f45822df5638bb129c32c10878e2651cb74081711d4d4ef30da47403195c07276a4dbcb60e650c35dbc40ba0bcfb48d4a2c625eb442dec476e8a18929a7a
7
+ data.tar.gz: 942ff614b651c87ab52726aa88564243fd60b3c87edff7670fcb61491f2a45516a8c91eed44119d5945a322f0598f9be28d3ab5d610146e9d488e261514bf0af
data/HISTORY.md CHANGED
@@ -1,3 +1,50 @@
1
+ ## 3.0.2
2
+
3
+ ### Added
4
+
5
+ * resque-web: Support IPv6 hosts in the server URL (#1938)
6
+
7
+ ### Fixed
8
+
9
+ * resque-web: Escape queue names, worker IDs, job classes, failed job details, Redis keys/values, and the reflected request path; serve `/stats.txt` as `text/plain` (#1946)
10
+ * resque-web: Fix the class filter link URL on the failed jobs page (#1934)
11
+ * Prefer `MultiJson.generate`/`parse` over the deprecated `dump`/`load` (#1944)
12
+ * Add tests covering which hooks run in which process (#1932)
13
+
14
+ ## 3.0.1
15
+
16
+ ### Fixed
17
+
18
+ * resque-web: Fix reflected XSS in the key sets endpoint (#1942)
19
+ * Address multi_json class name deprecation warning (#1940)
20
+ * Update the Rails initializer docs to load Redis config with `config_for` (#1936)
21
+ * Add tests covering queue priority ordering with wildcards (#1930)
22
+
23
+ ## 3.0.0
24
+
25
+ ### Breaking Changes
26
+
27
+ * **Minimum Ruby version is now 3.0.0** - Ruby 2.x is no longer supported
28
+ * **Minimum Sinatra version is now 2.0** - old Sinatra versions (0.9-1.x) are no longer supported
29
+ * **Rack 1.x is no longer supported** - Resque now requires Rack 2.x or greater
30
+ * **Minimum Rails version is now 7.2** - You can use Resque without Rails, but if you use it with Rails it must be a version that is still supported
31
+
32
+ ### Added
33
+
34
+ * Rack 3 support and switched default Rack handler to Puma (#1912)
35
+ * Ruby 3.4 and Rails 8.1 support (#1912 and #1906)
36
+ * Upstream Active Job adapter from Rails (#1906)
37
+ * Explicit `redis` (>= 4.0) and `base64` (~> 0.1) gem dependencies (#1922)
38
+ * Added `shutdown` hooks - allows plugins and adapters to know when a worker is shutting down, enabling features like Active Job Continuations (#1916, #1924)
39
+ * Added support for dynamic interval sleep - workers can now use a faster polling interval that automatically backs off when idle, reducing Redis load (#1920)
40
+
41
+ ### Fixed
42
+
43
+ * Fix circular require from Rails ActiveJob adapter (#1906)
44
+ * Fix failed job `retried_at` timezone data (#1918)
45
+ * Fix double Redis get when checking for paused workers (#1919)
46
+ * Documentation cleanup (#1903, #1917)
47
+
1
48
  ## 2.7.0
2
49
 
3
50
  ### Fixed
data/README.markdown CHANGED
@@ -39,15 +39,23 @@ The Resque frontend tells you what workers are doing, what workers are
39
39
  not doing, what queues you're using, what's in those queues, provides
40
40
  general usage stats, and helps you track failures.
41
41
 
42
- Resque now supports Ruby 2.3.0 and above.
43
- We will also only be supporting Redis 3.0 and above going forward.
42
+ Resque 3.0 requires Ruby 3.0.0 or newer.
44
43
 
45
- ### Note on the future of Resque
44
+ **Version Support:**
45
+ - Ruby: 3.0, 3.1, 3.2, 3.3, 3.4+
46
+ - Redis gem: 4.0+
47
+ - Rack: 2.x or 3.x
48
+ - Rails (for ActiveJob): 7.2+ (requires Ruby 3.1+ for Rails 8.0+)
46
49
 
47
- Would you like to be involved in Resque? Do you have thoughts about what
48
- Resque should be and do going forward? There's currently an [open discussion here](https://github.com/resque/resque/issues/1759)
49
- on just that topic, so please feel free to join in. We'd love to hear your thoughts
50
- and/or have people volunteer to be a part of the project!
50
+ ### Resque 3.0
51
+
52
+ Resque 3.0 is a major release that modernizes the codebase with updated dependency requirements:
53
+ - Requires Ruby 3.0+ (drops support for Ruby 2.x)
54
+ - Requires redis gem 4.0+ (tested with redis gem 4.x and 5.x)
55
+ - Requires Sinatra 2.0+ (with Rack 2.x or 3.x support via appropriate Sinatra version)
56
+ - Maintains compatibility with Rails 7.2+ and ActiveJob
57
+
58
+ If you need Ruby 2.x support, please use Resque 2.x.
51
59
 
52
60
  Example
53
61
  -------
@@ -133,15 +141,6 @@ require 'your/app' # Include this line if you want your workers to have access t
133
141
 
134
142
  #### Rails
135
143
 
136
- ##### Rails 7.1
137
-
138
- If you're using Rails 7.1.x, use [rack-session version 1.0.2](https://rubygems.org/gems/rack-session/versions/1.0.2). This is because resque-web's dependency, [Sinatra, isn't compatible with rack 3.0](https://github.com/sinatra/sinatra/issues/1797), which is [required by rack-session 2.0.0](https://rubygems.org/gems/rack-session/versions/2.0.0).
139
-
140
- ```
141
- gem 'rails', '~> 7.1'
142
- gem 'rack-session', '~> 1.0', '>= 1.0.2'
143
- ```
144
-
145
144
  To make resque specific changes, you can override the `resque:setup` job in `lib/tasks` (ex: `lib/tasks/resque.rake`). GitHub's setup task looks like this:
146
145
 
147
146
  ``` ruby
@@ -496,12 +495,14 @@ Here's our `config/resque.yml`:
496
495
  And our initializer:
497
496
 
498
497
  ``` ruby
499
- rails_root = ENV['RAILS_ROOT'] || File.dirname(__FILE__) + '/../..'
500
- rails_env = ENV['RAILS_ENV'] || 'development'
501
- config_file = rails_root + '/config/resque.yml'
498
+ config_file = 'config/resque.yml'
499
+ rails_env = ENV['RAILS_ENV'] || Rails.env
502
500
 
503
- resque_config = YAML::load(ERB.new(IO.read(config_file)).result)
501
+ resque_config = YAML::load_file(config_file)
504
502
  Resque.redis = resque_config[rails_env]
503
+
504
+ # OR auto load with current env
505
+ Resque.redis = Rails.application.config_for(:resque)
505
506
  ```
506
507
 
507
508
  Easy peasy! Why not just use `RAILS_ROOT` and `RAILS_ENV`? Because
@@ -633,7 +634,7 @@ Choose DelayedJob if:
633
634
  * You like numeric priorities
634
635
  * You're not doing a gigantic amount of jobs each day
635
636
  * Your queue stays small and nimble
636
- * There is not a lot failure / chaos
637
+ * There is not a lot of failure / chaos
637
638
  * You want to easily throw anything on the queue
638
639
  * You don't want to setup Redis
639
640
 
data/Rakefile CHANGED
@@ -28,7 +28,33 @@ Rake::TestTask.new do |test|
28
28
  test.verbose = true
29
29
  test.libs << "test"
30
30
  test.libs << "lib"
31
- test.test_files = FileList['test/**/*_test.rb']
31
+ test.test_files = FileList['test/**/*_test.rb'].exclude('test/active_job/**/*')
32
+ end
33
+
34
+ Rake::TestTask.new('test:activejob') do |test|
35
+ test.verbose = true
36
+ test.libs << "test"
37
+ test.libs << "lib"
38
+ test.libs << "test/active_job"
39
+ test.test_files = FileList['test/active_job/cases/*_test.rb']
40
+ end
41
+
42
+ task "env:aj_integration" do
43
+ ENV["AJ_INTEGRATION_TESTS"] = "1"
44
+ end
45
+
46
+ Rake::TestTask.new('test:activejob:integration' => 'env:aj_integration') do |t|
47
+ if Gem::Version.new(RUBY_VERSION) < Gem::Version.new("3.1")
48
+ puts "Integration tests require Ruby 3.1 or later"
49
+ exit 0
50
+ end
51
+
52
+ t.description = "Run integration tests for Resque::ActiveJob::Adapter"
53
+ t.libs << "test"
54
+ t.libs << "test/active_job"
55
+ t.test_files = FileList["test/active_job/integration/**/*_test.rb"]
56
+ t.verbose = true
57
+ t.warning = true
32
58
  end
33
59
 
34
60
  if command? :kicker
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/enumerable"
4
+ require "active_support/core_ext/array/access"
5
+
6
+ begin
7
+ require "resque-scheduler"
8
+ rescue LoadError
9
+ begin
10
+ require "resque_scheduler"
11
+ rescue LoadError
12
+ false
13
+ end
14
+ end
15
+
16
+ module ActiveJob
17
+ module QueueAdapters
18
+ remove_const(:ResqueAdapter) if defined?(ResqueAdapter)
19
+
20
+ # = Resque adapter for Active Job
21
+ #
22
+ # Resque (pronounced like "rescue") is a Redis-backed library for creating
23
+ # background jobs, placing those jobs on multiple queues, and processing
24
+ # them later.
25
+ #
26
+ # Read more about Resque {here}[https://github.com/resque/resque].
27
+ #
28
+ # To use Resque set the queue_adapter config to +:resque+.
29
+ #
30
+ # Rails.application.config.active_job.queue_adapter = :resque
31
+ class ResqueAdapter < ::ActiveJob::QueueAdapters::AbstractAdapter
32
+ def enqueue(job) # :nodoc:
33
+ JobWrapper.instance_variable_set(:@queue, job.queue_name)
34
+ Resque.enqueue_to job.queue_name, JobWrapper, job.serialize
35
+ end
36
+
37
+ def enqueue_at(job, timestamp) # :nodoc:
38
+ unless Resque.respond_to?(:enqueue_at_with_queue)
39
+ raise NotImplementedError, "To be able to schedule jobs with Resque you need the " \
40
+ "resque-scheduler gem. Please add it to your Gemfile and run bundle install"
41
+ end
42
+ Resque.enqueue_at_with_queue job.queue_name, timestamp, JobWrapper, job.serialize
43
+ end
44
+
45
+ class JobWrapper # :nodoc:
46
+ class << self
47
+ def perform(job_data)
48
+ ::ActiveJob::Base.execute job_data
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -78,7 +78,7 @@ module Resque
78
78
  def self.requeue(id, queue = nil)
79
79
  check_queue(queue)
80
80
  item = all(id)
81
- item['retried_at'] = Time.now.strftime("%Y/%m/%d %H:%M:%S")
81
+ item['retried_at'] = UTF8Util.clean(Time.now.strftime("%Y/%m/%d %H:%M:%S %Z"))
82
82
  data_store.update_item_in_failed_queue(id,Resque.encode(item))
83
83
  Job.create(item['queue'], item['payload']['class'], *item['payload']['args'])
84
84
  end
@@ -1,14 +1,19 @@
1
1
  require 'multi_json'
2
2
 
3
- # OkJson won't work because it doesn't serialize symbols
4
- # in the same way yajl and json do.
5
- if MultiJson.respond_to?(:adapter)
6
- raise "Please install the yajl-ruby or json gem" if MultiJson.adapter.to_s == 'MultiJson::Adapters::OkJson'
7
- elsif MultiJson.respond_to?(:engine)
8
- raise "Please install the yajl-ruby or json gem" if MultiJson.engine.to_s == 'MultiJson::Engines::OkJson'
9
- end
10
-
11
3
  module Resque
4
+ # multi_json renamed it's top-level constant from MultiJson to MultiJSON,
5
+ # keeping MultiJson as a deprecated alias until v2.0. Reference whichever name the
6
+ # installed version exposes so we stay compatible with future versions of multi_json
7
+ MultiJson = defined?(::MultiJSON) ? ::MultiJSON : ::MultiJson
8
+
9
+ # OkJson won't work because it doesn't serialize symbols
10
+ # in the same way yajl and json do.
11
+ if MultiJson.respond_to?(:adapter)
12
+ raise "Please install the yajl-ruby or json gem" if MultiJson.adapter.to_s.end_with?('::OkJson')
13
+ elsif MultiJson.respond_to?(:engine)
14
+ raise "Please install the yajl-ruby or json gem" if MultiJson.engine.to_s.end_with?('::OkJson')
15
+ end
16
+
12
17
  # Methods used by various classes in Resque.
13
18
  module Helpers
14
19
  class DecodeException < StandardError; end
@@ -6,5 +6,11 @@ module Resque
6
6
  # redefine ths task to load the rails env
7
7
  task "resque:setup" => :environment
8
8
  end
9
+
10
+ initializer "resque.active_job" do
11
+ ActiveSupport.on_load(:active_job) do
12
+ require "active_job/queue_adapters/resque_adapter"
13
+ end
14
+ end
9
15
  end
10
16
  end
@@ -5,7 +5,7 @@
5
5
  <% end %>
6
6
 
7
7
  <% unless failed_size.zero? %>
8
- <form method="POST" action="<%= u "failed#{'/' + params[:queue] if params[:queue]}/clear" %>">
8
+ <form method="POST" action="<%= h u("failed#{'/' + params[:queue] if params[:queue]}/clear") %>">
9
9
  <input type="submit" name="" value="Clear <%= params[:queue] ? "'#{escape_html(params[:queue])}'" : 'Failed' %> Jobs" class="confirmSubmission" />
10
10
  </form>
11
11
 
@@ -14,7 +14,7 @@
14
14
  <input type="submit" name="" value="Clear Retried Jobs" onclick='return confirm("Are you absolutely sure? This cannot be undone.");' />
15
15
  </form>
16
16
  <% end %>
17
- <form method="POST" action="<%= u "failed#{'/' + params[:queue] if params[:queue]}/requeue/all" %>">
17
+ <form method="POST" action="<%= h u("failed#{'/' + params[:queue] if params[:queue]}/requeue/all") %>">
18
18
  <input type="submit" name="" value="Retry <%= params[:queue] ? "'#{escape_html(params[:queue])}'" : 'Failed' %> Jobs" class="confirmSubmission" />
19
19
  </form>
20
20
  <% end %>
@@ -2,28 +2,28 @@
2
2
  <dl>
3
3
  <% if job.nil? %>
4
4
  <dt>Error</dt>
5
- <dd>Job <%= id %> could not be parsed; perhaps it contains invalid JSON?</dd>
5
+ <dd>Job <%= h id %> could not be parsed; perhaps it contains invalid JSON?</dd>
6
6
  <% else %>
7
7
  <dt>Worker</dt>
8
8
  <dd>
9
- <a href="<%= u(:workers, job['worker']) %>"><%= job['worker'].split(':')[0...2].join(':') %></a> on <b class='queue-tag'><%= job['queue'] %></b > at <b><span class="time"><%= DateTime.parse(job['failed_at']).strftime(failed_date_format) %></span></b>
9
+ <a href="<%= h u(:workers, job['worker']) %>"><%= h job['worker'].split(':')[0...2].join(':') %></a> on <b class='queue-tag'><%= h job['queue'] %></b > at <b><span class="time"><%= DateTime.parse(job['failed_at']).strftime(failed_date_format) %></span></b>
10
10
  <% if job['retried_at'] %>
11
11
  <div class='retried'>
12
12
  Retried <b><span class="time"><%= DateTime.parse(job['retried_at']).strftime(failed_date_format) %></span></b>
13
- <a href="<%= u "#{queue}/remove/#{id}" %>" class="remove" rel="remove">Remove</a>
13
+ <a href="<%= h u("#{queue}/remove/#{id}") %>" class="remove" rel="remove">Remove</a>
14
14
  </div>
15
15
  <% else %>
16
16
  <div class='controls'>
17
- <a href="<%= u "#{queue}/requeue/#{id}" %>" rel="retry">Retry</a>
17
+ <a href="<%= h u("#{queue}/requeue/#{id}") %>" rel="retry">Retry</a>
18
18
  or
19
- <a href="<%= u "#{queue}/remove/#{id}" %>" rel="remove">Remove</a>
19
+ <a href="<%= h u("#{queue}/remove/#{id}") %>" rel="remove">Remove</a>
20
20
  </div>
21
21
  <% end %>
22
22
  </dd>
23
23
  <dt>Class</dt>
24
24
  <dd>
25
25
  <% if job['payload'] && job['payload']['class'] %>
26
- <a href="<%= u "failed/#{params[:queue]}?class=#{job['payload']['class']}" %>">
26
+ <a href="<%= h u("#{queue}?class=#{job['payload']['class']}") %>">
27
27
  <%= partial :job_class, :job => job['payload'] %>
28
28
  </a>
29
29
  <% else %>
@@ -33,7 +33,7 @@
33
33
  <dt>Arguments</dt>
34
34
  <dd><pre><%=h job['payload'] ? show_args(job['payload']['args']) : 'nil' %></pre></dd>
35
35
  <dt>Exception</dt>
36
- <dd><code><%= job['exception'] %></code></dd>
36
+ <dd><code><%= h job['exception'] %></code></dd>
37
37
  <dt>Error</dt>
38
38
  <dd class='error'>
39
39
  <% if job['backtrace'] %>
@@ -7,14 +7,14 @@
7
7
 
8
8
  <% Resque::Failure.queues.sort.each do |queue| %>
9
9
  <tr>
10
- <th><b class="queue-tag"><a href="<%= u "/failed/#{queue}" %>"><%= queue %></a></b></th>
10
+ <th><b class="queue-tag"><a href="<%= h u("/failed/#{queue}") %>"><%= h queue %></a></b></th>
11
11
  <th style="width:75px;" class="center"><%= Resque::Failure.count(queue) %></th>
12
12
  </tr>
13
13
 
14
14
  <% failed_class_counts(queue).sort_by { |name,_| name }.each do |k, v| %>
15
- <tr id="<%= k %>">
15
+ <tr id="<%= h k %>">
16
16
  <td>
17
- <a href="<%= u "/failed/#{queue}?class=#{k}" %>"><span class="failed failed_class"><%= k %></span></a>
17
+ <a href="<%= h u("/failed/#{queue}?class=#{k}") %>"><span class="failed failed_class"><%= h k %></span></a>
18
18
  </td>
19
19
  <td style="text-align: center;" class="failed<%= (v.to_i > 1000) ? '_many' : '' %>"><%= v %></td>
20
20
  </tr>
@@ -1,8 +1,8 @@
1
1
  <% if job['class'] == 'ActiveJob::QueueAdapters::ResqueAdapter::JobWrapper' %>
2
- <code><%= job['args'].first['job_class'] %></code>
2
+ <code><%= h job['args'].first['job_class'] %></code>
3
3
  <small>
4
4
  <a href="http://edgeguides.rubyonrails.org/active_job_basics.html" rel="noopener noreferrer" target="_blank">(via ActiveJob)</a>
5
5
  </small>
6
6
  <% else %>
7
- <code><%= job['class'] %></code>
7
+ <code><%= h job['class'] %></code>
8
8
  <% end %>
@@ -2,12 +2,12 @@
2
2
 
3
3
  <p class='sub'><%= page_entries_info start = params[:start].to_i, start + 20, size = redis_get_size(key) %></p>
4
4
 
5
- <h1>Key "<%= key %>" is a <%= resque.redis.type key %></h1>
5
+ <h1>Key "<%= escape_html(key) %>" is a <%= resque.redis.type key %></h1>
6
6
  <table>
7
7
  <% for row in redis_get_value_as_array(key, start) %>
8
8
  <tr>
9
9
  <td>
10
- <%= row %>
10
+ <%= h row %>
11
11
  </td>
12
12
  </tr>
13
13
  <% end %>
@@ -4,7 +4,7 @@
4
4
  <table>
5
5
  <tr>
6
6
  <td>
7
- <%= redis_get_value_as_array(key) %>
7
+ <%= h redis_get_value_as_array(key) %>
8
8
  </td>
9
9
  </tr>
10
10
  </table>
@@ -19,7 +19,7 @@
19
19
  </ul>
20
20
  <% if Resque.redis.namespace != :resque %>
21
21
  <abbr class="namespace" title="Resque's Redis Namespace">
22
- <%= Resque.redis.namespace %>
22
+ <%= h Resque.redis.namespace %>
23
23
  </abbr>
24
24
  <% end %>
25
25
  </div>
@@ -27,7 +27,7 @@
27
27
  <% if defined?(@subtabs) && @subtabs %>
28
28
  <ul class='subnav'>
29
29
  <% for subtab in @subtabs %>
30
- <li <%= class_if_current "#{current_section}/#{subtab}" %>><a href="<%= current_section %>/<%= subtab %>"><span><%= subtab %></span></a></li>
30
+ <li <%= class_if_current "#{current_section}/#{subtab}" %>><a href="<%= h current_section %>/<%= h subtab %>"><span><%= h subtab %></span></a></li>
31
31
  <% end %>
32
32
  </ul>
33
33
  <% end %>
@@ -38,7 +38,7 @@
38
38
 
39
39
  <div id="footer">
40
40
  <p>Powered by <a href="http://github.com/resque/resque">Resque</a> v<%=Resque::VERSION%></p>
41
- <p>Connected to Redis namespace <%= Resque.redis.namespace %> on <%= h Resque.redis_id %></p>
41
+ <p>Connected to Redis namespace <%= h Resque.redis.namespace %> on <%= h Resque.redis_id %></p>
42
42
  </div>
43
43
 
44
44
  </body>
@@ -4,19 +4,19 @@
4
4
  <%if start - per_page >= 0 || start + per_page <= size%>
5
5
  <div class='pagination'>
6
6
  <% if start - per_page >= 0 %>
7
- <a href="<%= current_page %>?start=<%= start - per_page %>" class='less'>&laquo; Previous</a>
7
+ <a href="<%= h current_page %>?start=<%= start - per_page %>" class='less'>&laquo; Previous</a>
8
8
  <% end %>
9
9
 
10
10
  <% (size / per_page.to_f).ceil.times do |page_num| %>
11
11
  <% if start == page_num * per_page %>
12
12
  <span><%= page_num + 1 %></span>
13
13
  <% else %>
14
- <a href="<%= current_page %>?start=<%= page_num * per_page %>"> <%= page_num + 1 %></a>
14
+ <a href="<%= h current_page %>?start=<%= page_num * per_page %>"> <%= page_num + 1 %></a>
15
15
  <% end %>
16
16
  <% end %>
17
17
 
18
18
  <% if start + per_page < size %>
19
- <a href="<%= current_page %>?start=<%= start + per_page %>" class='more'>Next &raquo;</a>
19
+ <a href="<%= h current_page %>?start=<%= start + per_page %>" class='more'>Next &raquo;</a>
20
20
  <% end %>
21
21
  </div>
22
22
  <%end%>
@@ -1,2 +1,2 @@
1
1
  <%= partial :job_class, :job => job['payload'] %>
2
- <small><a class="queue time" href="<%=u "/working/#{worker}" %>"><%= job['run_at'] %></a></small>
2
+ <small><a class="queue time" href="<%= h u("/working/#{worker}") %>"><%= h job['run_at'] %></a></small>
@@ -2,8 +2,8 @@
2
2
 
3
3
  <% if current_queue = params[:id] %>
4
4
 
5
- <h1>Pending jobs on <span class='hl'><%= h escape_html(current_queue) %></span></h1>
6
- <form method="POST" action="<%=u "/queues/#{escape_html(current_queue)}/remove" %>" class='remove-queue'>
5
+ <h1>Pending jobs on <span class='hl'><%= h current_queue %></span></h1>
6
+ <form method="POST" action="<%= h u("/queues/#{current_queue}/remove") %>" class='remove-queue'>
7
7
  <input type='submit' name='' value='Remove Queue' class="confirmSubmission" />
8
8
  </form>
9
9
  <p class='sub'><%= page_entries_info start = params[:start].to_i, start + 19, size = resque.size(current_queue), 'job' %></p>
@@ -36,14 +36,14 @@
36
36
  </tr>
37
37
  <% resque.queues.sort_by { |q| q.to_s }.each do |queue| %>
38
38
  <tr>
39
- <td class='queue'><a class="queue" href="<%= u "queues/#{queue}" %>"><%= queue %></a></td>
39
+ <td class='queue'><a class="queue" href="<%= h u("queues/#{queue}") %>"><%= h queue %></a></td>
40
40
  <td class='size'><%= resque.size queue %></td>
41
41
  </tr>
42
42
  <% end %>
43
43
  <% if failed_multiple_queues? %>
44
44
  <% Resque::Failure.queues.sort_by { |q| q.to_s }.each_with_index do |queue, i| %>
45
45
  <tr class="<%= Resque::Failure.count(queue).zero? ? "failed" : "failure" %><%= " first_failure" if i.zero? %>">
46
- <td class='queue failed'><a class="queue" href="<%= u "failed/#{queue}" %>"><%= queue %></a></td>
46
+ <td class='queue failed'><a class="queue" href="<%= h u("failed/#{queue}") %>"><%= h queue %></a></td>
47
47
  <td class='size'><%= Resque::Failure.count(queue) %></td>
48
48
  </tr>
49
49
  <% end %>
@@ -11,7 +11,7 @@
11
11
  <% for key, value in resque.info.to_a.sort_by { |i| i[0].to_s } %>
12
12
  <tr>
13
13
  <th>
14
- <%= key %>
14
+ <%= h key %>
15
15
  </th>
16
16
  <td>
17
17
  <%= h value %>
@@ -27,10 +27,10 @@
27
27
  <% for key, value in resque.redis.redis.info.to_a.sort_by { |i| i[0].to_s } %>
28
28
  <tr>
29
29
  <th>
30
- <%= key %>
30
+ <%= h key %>
31
31
  </th>
32
32
  <td>
33
- <%= value %>
33
+ <%= h value %>
34
34
  </td>
35
35
  </tr>
36
36
  <% end %>
@@ -39,7 +39,7 @@
39
39
  <% elsif params[:id] == 'keys' %>
40
40
 
41
41
  <h1>Keys owned by <%= h resque.redis_id %></h1>
42
- <p class='sub'>(All keys are actually prefixed with "<%= Resque.redis.namespace %>:")</p>
42
+ <p class='sub'>(All keys are actually prefixed with "<%= h Resque.redis.namespace %>:")</p>
43
43
  <table class='stats'>
44
44
  <tr>
45
45
  <th>key</th>
@@ -49,7 +49,7 @@
49
49
  <% for key in resque.keys.sort %>
50
50
  <tr>
51
51
  <th>
52
- <a href="<%=u "/stats/keys/#{key}" %>"><%= key %></a>
52
+ <a href="<%= h u("/stats/keys/#{key}") %>"><%= h key %></a>
53
53
  </th>
54
54
  <td><%= resque.redis.type key %></td>
55
55
  <td><%= redis_get_size key %></td>
@@ -2,7 +2,7 @@
2
2
 
3
3
  <% if params[:id] && worker = Resque::Worker.find(params[:id]) %>
4
4
 
5
- <h1>Worker <%= worker %></h1>
5
+ <h1>Worker <%= h worker %></h1>
6
6
  <table class='workers'>
7
7
  <tr>
8
8
  <th>&nbsp;</th>
@@ -16,14 +16,14 @@
16
16
  <th>Processing</th>
17
17
  </tr>
18
18
  <tr>
19
- <td class='icon'><img src="<%=u state = worker.state %>.png" alt="<%= state %>" title="<%= state %>"></td>
19
+ <td class='icon'><img src="<%= h u(state = worker.state) %>.png" alt="<%= h state %>" title="<%= h state %>"></td>
20
20
 
21
21
  <% host, pid, queues = worker.to_s.split(':') %>
22
- <td><%= host %></td>
23
- <td><%= pid %></td>
24
- <td><span class="time"><%= worker.started %></span></td>
25
- <td><span class="time"><%= worker.heartbeat %></span></td>
26
- <td class='queues'><%= queues.split(',').map { |q| '<a class="queue-tag" href="' + u("/queues/#{q}") + '">' + q + '</a>'}.join('') %></td>
22
+ <td><%= h host %></td>
23
+ <td><%= h pid %></td>
24
+ <td><span class="time"><%= h worker.started %></span></td>
25
+ <td><span class="time"><%= h worker.heartbeat %></span></td>
26
+ <td class='queues'><%= queues.split(',').map { |q| '<a class="queue-tag" href="' + h(u("/queues/#{q}")) + '">' + h(q) + '</a>'}.join('') %></td>
27
27
  <td><%= worker.processed %></td>
28
28
  <td><%= worker.failed %></td>
29
29
  <td class='process'>
@@ -60,11 +60,11 @@
60
60
  </tr>
61
61
  <% for worker in (workers = workers.sort_by { |w| w.to_s }) %>
62
62
  <tr class="<%=state = worker.state%>">
63
- <td class='icon'><img src="<%=u state %>.png" alt="<%= state %>" title="<%= state %>"></td>
63
+ <td class='icon'><img src="<%= h u(state) %>.png" alt="<%= h state %>" title="<%= h state %>"></td>
64
64
 
65
65
  <% host, pid, queues = worker.to_s.split(':') %>
66
- <td class='where'><a href="<%=u "workers/#{worker}"%>"><%= host %>:<%= pid %></a></td>
67
- <td class='queues'><%= queues.split(',').map { |q| '<a class="queue-tag" href="' + u("/queues/#{q}") + '">' + q + '</a>'}.join('') %></td>
66
+ <td class='where'><a href="<%= h u("workers/#{worker}") %>"><%= h host %>:<%= h pid %></a></td>
67
+ <td class='queues'><%= queues.split(',').map { |q| '<a class="queue-tag" href="' + h(u("/queues/#{q}")) + '">' + h(q) + '</a>'}.join('') %></td>
68
68
 
69
69
  <td class='process'>
70
70
  <% data = worker.processing || {} %>
@@ -95,7 +95,7 @@
95
95
  </tr>
96
96
  <% for hostname, workers in worker_hosts.sort_by { |h,w| h } %>
97
97
  <tr>
98
- <td class='queue'><a class="queue" href="<%= u "workers/#{hostname}" %>"><%= hostname %></a></td>
98
+ <td class='queue'><a class="queue" href="<%= h u("workers/#{hostname}") %>"><%= h hostname %></a></td>
99
99
  <td class='size'><%= workers.size %></td>
100
100
  </tr>
101
101
  <% end %>
@@ -1,5 +1,5 @@
1
1
  <% if params[:id] && (current_worker = Resque::Worker.find(params[:id])) && (data = current_worker.job) %>
2
- <h1><%= current_worker %>'s job</h1>
2
+ <h1><%= h current_worker %>'s job</h1>
3
3
 
4
4
  <table>
5
5
  <tr>
@@ -13,13 +13,13 @@
13
13
  <tr>
14
14
  <td><img src="<%=u 'working.png' %>" alt="working" title="working"></td>
15
15
  <% host, pid, _ = current_worker.to_s.split(':') %>
16
- <td><a href="<%=u "/workers/#{current_worker}" %>"><%= host %>:<%= pid %></a></td>
16
+ <td><a href="<%= h u("/workers/#{current_worker}") %>"><%= h host %>:<%= h pid %></a></td>
17
17
  <% queue = data['queue'] %>
18
- <td><a class="queue" href="<%=u "/queues/#{queue}" %>"><%= queue %></a></td>
19
- <td><span class="time"><%= data['run_at'] %></span></td>
18
+ <td><a class="queue" href="<%= h u("/queues/#{queue}") %>"><%= h queue %></a></td>
19
+ <td><span class="time"><%= h data['run_at'] %></span></td>
20
20
  <% payload = data.key?('payload') ? data['payload'] : {} %>
21
21
  <td>
22
- <code><%= payload.key?('class') ? payload['class'] : "—" %></code>
22
+ <code><%= payload.key?('class') ? h(payload['class']) : "—" %></code>
23
23
  </td>
24
24
  <td><pre><%=h payload.key?('args') ? show_args(payload['args']) : "—" %></pre></td>
25
25
  </tr>
@@ -51,11 +51,11 @@
51
51
 
52
52
  <% worker_jobs.sort_by { |_w, j| j['run_at'] ? j['run_at'].to_s() : '' }.each do |worker, job| %>
53
53
  <tr>
54
- <td class='icon'><img src="<%=u state = worker.state %>.png" alt="<%= state %>" title="<%= state %>"></td>
54
+ <td class='icon'><img src="<%= h u(state = worker.state) %>.png" alt="<%= h state %>" title="<%= h state %>"></td>
55
55
  <% host, pid, _queues = worker.to_s.split(':') %>
56
- <td class='where'><a href="<%=u "/workers/#{worker}" %>"><%= host %>:<%= pid %></a></td>
56
+ <td class='where'><a href="<%= h u("/workers/#{worker}") %>"><%= h host %>:<%= h pid %></a></td>
57
57
  <td class='queues queue'>
58
- <a class="queue-tag" href="<%=u "/queues/#{job['queue']}" %>"><%= job['queue'] %></a>
58
+ <a class="queue-tag" href="<%= h u("/queues/#{job['queue']}") %>"><%= h job['queue'] %></a>
59
59
  </td>
60
60
  <td class='process'>
61
61
  <% if job['queue'] %>
data/lib/resque/server.rb CHANGED
@@ -168,7 +168,7 @@ module Resque
168
168
  stats << "queues.#{queue}=#{Resque.size(queue)}"
169
169
  end
170
170
 
171
- content_type 'text/html'
171
+ content_type 'text/plain'
172
172
  stats.join "\n"
173
173
  end
174
174
 
@@ -29,7 +29,7 @@ module Resque
29
29
  def tab(name)
30
30
  dname = name.to_s.downcase
31
31
  path = url_path(dname)
32
- "<li #{class_if_current(path)}><a href='#{path.gsub(" ", "_")}'>#{name}</a></li>"
32
+ "<li #{class_if_current(path)}><a href='#{h path.gsub(" ", "_")}'>#{h name}</a></li>"
33
33
  end
34
34
 
35
35
  def tabs
@@ -112,7 +112,7 @@ module Resque
112
112
  if defined?(@polling) && @polling
113
113
  text = "Last Updated: #{Time.now.strftime("%H:%M:%S")}"
114
114
  else
115
- text = "<a href='#{u(request.path_info)}.poll' rel='poll'>Live Poll!!</a>"
115
+ text = "<a href='#{h u(request.path_info)}.poll' rel='poll'>Live Poll!!</a>"
116
116
  end
117
117
  "<p class='poll'>#{text}</p>"
118
118
  end
data/lib/resque/tasks.rb CHANGED
@@ -17,7 +17,11 @@ namespace :resque do
17
17
 
18
18
  worker.prepare
19
19
  worker.log "Starting worker #{worker}"
20
- worker.work(ENV['INTERVAL'] || 5) # interval, will block
20
+ # will block until a shutdown signal is received
21
+ worker.work(ENV["INTERVAL"],
22
+ max_interval: ENV['MAX_INTERVAL'],
23
+ min_interval: ENV['MIN_INTERVAL'],
24
+ backoff_interval: ENV['BACKOFF_INTERVAL'])
21
25
  end
22
26
 
23
27
  desc "Start multiple Resque workers. Should only be used in dev mode."
@@ -1,3 +1,3 @@
1
1
  module Resque
2
- VERSION = '2.7.0'
2
+ VERSION = '3.0.2'
3
3
  end
@@ -3,6 +3,10 @@ require 'logger'
3
3
  require 'optparse'
4
4
  require 'fileutils'
5
5
  require 'rack'
6
+ begin
7
+ require 'rackup'
8
+ rescue LoadError
9
+ end
6
10
  require 'resque/server'
7
11
 
8
12
  # only used with `bin/resque-web`
@@ -30,7 +34,7 @@ module Resque
30
34
 
31
35
  @args = load_options(runtime_args)
32
36
 
33
- @rack_handler = (s = options[:rack_handler]) ? Rack::Handler.get(s) : setup_rack_handler
37
+ @rack_handler = (s = options[:rack_handler]) ? self.class.get_rackup_or_rack_handler.get(s) : setup_rack_handler
34
38
 
35
39
  case option_parser.command
36
40
  when :help
@@ -81,7 +85,8 @@ module Resque
81
85
  end
82
86
 
83
87
  def url
84
- "http://#{host}:#{port}"
88
+ h = host.include?(':') ? "[#{host}]" : host
89
+ "http://#{h}:#{port}"
85
90
  end
86
91
 
87
92
  def before_run
@@ -270,6 +275,10 @@ module Resque
270
275
  self.class.logger
271
276
  end
272
277
 
278
+ def self.get_rackup_or_rack_handler
279
+ defined?(::Rackup::Handler) && ::Rack.release >= '3' ? ::Rackup::Handler : ::Rack::Handler
280
+ end
281
+
273
282
  private
274
283
  def setup_rack_handler
275
284
  # First try to set Rack handler via a special hook we honor
@@ -284,24 +293,25 @@ module Resque
284
293
  handler = nil
285
294
  @app.server.each do |server|
286
295
  begin
287
- handler = Rack::Handler.get(server)
296
+ handler = self.class.get_rackup_or_rack_handler.get(server)
288
297
  break
289
298
  rescue LoadError, NameError
290
299
  next
291
300
  end
292
301
  end
293
- raise 'No available Rack handler (e.g. WEBrick, Thin, Puma, etc.) was found.' if handler.nil?
302
+ raise 'No available Rack handler (e.g. WEBrick, Puma, etc.) was found.' if handler.nil?
294
303
 
295
304
  handler
296
305
 
297
306
  # :server might be set explicitly to a single option like "mongrel"
298
307
  else
299
- Rack::Handler.get(@app.server)
308
+ self.class.get_rackup_or_rack_handler.get(@app.server)
300
309
  end
301
310
 
302
- # If all else fails, we'll use Thin
311
+ # If all else fails, we'll use Puma
303
312
  else
304
- JRUBY ? Rack::Handler::WEBrick : Rack::Handler::Thin
313
+ rack_server = JRUBY ? 'webrick' : 'puma'
314
+ self.class.get_rackup_or_rack_handler.get(rack_server)
305
315
  end
306
316
  end
307
317
 
data/lib/resque/worker.rb CHANGED
@@ -143,6 +143,7 @@ module Resque
143
143
  def initialize(*queues)
144
144
  @shutdown = nil
145
145
  @paused = nil
146
+ @cached_pause_value = nil
146
147
  @before_first_fork_hook_ran = false
147
148
 
148
149
  @heartbeat_thread = nil
@@ -237,20 +238,43 @@ module Resque
237
238
  # The default is 5 seconds, but for a semi-active site you may
238
239
  # want to use a smaller value.
239
240
  #
241
+ # Can also be passed 3 interval floats: max, min, backoff.
242
+ # The actual sleep amount will float between these min/max
243
+ # bounds.
244
+ #
245
+ # If a job is picked up we sleep for the minimum amount of
246
+ # time, but as the queues empty we increase the backoff to the
247
+ # max interval. This prevents idle workers from hammering the
248
+ # redis server with lpop requests.
249
+ #
240
250
  # Also accepts a block which will be passed the job as soon as it
241
251
  # has completed processing. Useful for testing.
242
- def work(interval = 5.0, &block)
243
- interval = Float(interval)
252
+ def work(interval = 5.0,
253
+ min_interval: nil, # defaults to interval
254
+ max_interval: nil, # defaults to interval
255
+ backoff_interval: nil, # defaults to 0.1
256
+ &block)
257
+ interval = Float(interval || 5.0)
258
+ max_interval = Float(max_interval || interval)
259
+ min_interval = Float(min_interval || interval).clamp(nil, max_interval)
260
+ backoff_interval = Float(backoff_interval || 0.1).clamp(nil, max_interval)
261
+ interval = interval.clamp(min_interval, max_interval)
244
262
  startup
245
263
 
246
264
  loop do
247
265
  break if shutdown?
248
266
 
249
- unless work_one_job(&block)
267
+ if work_one_job(&block)
268
+ interval = min_interval
269
+ else
250
270
  state_change
251
271
  break if interval.zero?
272
+
273
+ interval = (interval + backoff_interval)
274
+ .clamp(nil, max_interval)
275
+
252
276
  log_with_severity :debug, "Sleeping for #{interval} seconds"
253
- procline paused? ? "Paused" : "Waiting for #{queues.join(',')}"
277
+ procline @cached_pause_value ? "Paused" : "Waiting for #{queues.join(',')}"
254
278
  sleep interval
255
279
  end
256
280
  end
@@ -260,6 +284,7 @@ module Resque
260
284
  rescue Exception => exception
261
285
  return if exception.class == SystemExit && !@child && run_at_exit_hooks
262
286
  log_with_severity :error, "Failed to start worker : #{exception.inspect}"
287
+ log_with_severity :error, exception.backtrace.join("\n")
263
288
  unregister_worker(exception)
264
289
  run_hook :worker_exit
265
290
  end
@@ -441,6 +466,8 @@ module Resque
441
466
  def shutdown
442
467
  log_with_severity :info, 'Exiting...'
443
468
  @shutdown = true
469
+ run_hook :shutdown
470
+ true
444
471
  end
445
472
 
446
473
  # Kill the child and shutdown immediately.
@@ -579,7 +606,7 @@ module Resque
579
606
 
580
607
  # are we paused?
581
608
  def paused?
582
- @paused || redis.get('pause-all-workers').to_s.strip.downcase == 'true'
609
+ @cached_pause_value = @paused || redis.get('pause-all-workers').to_s.strip.downcase == 'true'
583
610
  end
584
611
 
585
612
  # Stop processing jobs after the current one has completed (if we're
data/lib/resque.rb CHANGED
@@ -31,8 +31,15 @@ module Resque
31
31
 
32
32
  # Given a Ruby object, returns a string suitable for storage in a
33
33
  # queue.
34
+ #
35
+ # multi_json has renamed its core methods twice: first encode/decode became
36
+ # dump/load, then multi_json 1.21 renamed dump/load to generate/parse. Old
37
+ # names keep working as deprecated aliases. Check the newest name first so
38
+ # we prefer it while staying compatible with older installed versions.
34
39
  def encode(object)
35
- if MultiJson.respond_to?(:dump) && MultiJson.respond_to?(:load)
40
+ if MultiJson.respond_to?(:generate) && MultiJson.respond_to?(:parse)
41
+ MultiJson.generate object
42
+ elsif MultiJson.respond_to?(:dump) && MultiJson.respond_to?(:load)
36
43
  MultiJson.dump object
37
44
  else
38
45
  MultiJson.encode object
@@ -40,16 +47,20 @@ module Resque
40
47
  end
41
48
 
42
49
  # Given a string, returns a Ruby object.
50
+ #
51
+ # See `Resque.encode`, above, for why generate/parse are checked before dump/load.
43
52
  def decode(object)
44
53
  return unless object
45
54
 
46
55
  begin
47
- if MultiJson.respond_to?(:dump) && MultiJson.respond_to?(:load)
56
+ if MultiJson.respond_to?(:generate) && MultiJson.respond_to?(:parse)
57
+ MultiJson.parse object
58
+ elsif MultiJson.respond_to?(:dump) && MultiJson.respond_to?(:load)
48
59
  MultiJson.load object
49
60
  else
50
61
  MultiJson.decode object
51
62
  end
52
- rescue ::MultiJson::DecodeError => e
63
+ rescue MultiJson::DecodeError => e
53
64
  raise Helpers::DecodeException, e.message, e.backtrace
54
65
  end
55
66
  end
@@ -251,7 +262,7 @@ module Resque
251
262
  register_hook(:before_fork, block)
252
263
  end
253
264
 
254
- # The `after_fork` hook will be run in the child process and is passed
265
+ # The `after_fork` hook will be run in the **child** process and is passed
255
266
  # the current job. Any changes you make, therefore, will only live as
256
267
  # long as the job currently being processed.
257
268
  #
@@ -266,7 +277,7 @@ module Resque
266
277
  register_hook(:after_fork, block)
267
278
  end
268
279
 
269
- # The `before_pause` hook will be run in the parent process before the
280
+ # The `before_pause` hook will be run in the **parent** process before the
270
281
  # worker has paused processing (via #pause_processing or SIGUSR2).
271
282
  def before_pause(&block)
272
283
  block ? register_hook(:before_pause, block) : hooks(:before_pause)
@@ -277,7 +288,7 @@ module Resque
277
288
  register_hook(:before_pause, block)
278
289
  end
279
290
 
280
- # The `after_pause` hook will be run in the parent process after the
291
+ # The `after_pause` hook will be run in the **parent** process after the
281
292
  # worker has paused (via SIGCONT).
282
293
  def after_pause(&block)
283
294
  block ? register_hook(:after_pause, block) : hooks(:after_pause)
@@ -316,6 +327,20 @@ module Resque
316
327
  register_hook(:worker_exit, block)
317
328
  end
318
329
 
330
+ # The `shutdown` hook will be run in the **parent** process
331
+ # when the worker has received a signal to stop processing
332
+ #
333
+ # Call with a block to register a hook.
334
+ # Call with no arguments to return all registered hooks.
335
+ def shutdown(&block)
336
+ block ? register_hook(:shutdown, block) : hooks(:shutdown)
337
+ end
338
+
339
+ # Register a shutdown proc.
340
+ def shutdown=(block)
341
+ register_hook(:shutdown, block)
342
+ end
343
+
319
344
  def to_s
320
345
  "Resque Client connected to #{redis_id}"
321
346
  end
metadata CHANGED
@@ -1,18 +1,45 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: resque
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.7.0
4
+ version: 3.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Wanstrath
8
8
  - Steve Klabnik
9
9
  - Terence Lee
10
10
  - Michael Bianco
11
- autorequire:
12
11
  bindir: bin
13
12
  cert_chain: []
14
- date: 2024-12-30 00:00:00.000000000 Z
13
+ date: 1980-01-02 00:00:00.000000000 Z
15
14
  dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: base64
17
+ requirement: !ruby/object:Gem::Requirement
18
+ requirements:
19
+ - - "~>"
20
+ - !ruby/object:Gem::Version
21
+ version: '0.1'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ requirements:
26
+ - - "~>"
27
+ - !ruby/object:Gem::Version
28
+ version: '0.1'
29
+ - !ruby/object:Gem::Dependency
30
+ name: logger
31
+ requirement: !ruby/object:Gem::Requirement
32
+ requirements:
33
+ - - ">="
34
+ - !ruby/object:Gem::Version
35
+ version: '0'
36
+ type: :runtime
37
+ prerelease: false
38
+ version_requirements: !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: '0'
16
43
  - !ruby/object:Gem::Dependency
17
44
  name: redis-namespace
18
45
  requirement: !ruby/object:Gem::Requirement
@@ -27,20 +54,34 @@ dependencies:
27
54
  - - "~>"
28
55
  - !ruby/object:Gem::Version
29
56
  version: '1.6'
57
+ - !ruby/object:Gem::Dependency
58
+ name: redis
59
+ requirement: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ version: '4.0'
64
+ type: :runtime
65
+ prerelease: false
66
+ version_requirements: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ version: '4.0'
30
71
  - !ruby/object:Gem::Dependency
31
72
  name: sinatra
32
73
  requirement: !ruby/object:Gem::Requirement
33
74
  requirements:
34
75
  - - ">="
35
76
  - !ruby/object:Gem::Version
36
- version: 0.9.2
77
+ version: '2.0'
37
78
  type: :runtime
38
79
  prerelease: false
39
80
  version_requirements: !ruby/object:Gem::Requirement
40
81
  requirements:
41
82
  - - ">="
42
83
  - !ruby/object:Gem::Version
43
- version: 0.9.2
84
+ version: '2.0'
44
85
  - !ruby/object:Gem::Dependency
45
86
  name: multi_json
46
87
  requirement: !ruby/object:Gem::Requirement
@@ -70,7 +111,7 @@ dependencies:
70
111
  - !ruby/object:Gem::Version
71
112
  version: '1'
72
113
  - !ruby/object:Gem::Dependency
73
- name: thin
114
+ name: puma
74
115
  requirement: !ruby/object:Gem::Requirement
75
116
  requirements:
76
117
  - - ">="
@@ -127,6 +168,7 @@ files:
127
168
  - Rakefile
128
169
  - bin/resque
129
170
  - bin/resque-web
171
+ - lib/active_job/queue_adapters/resque_adapter.rb
130
172
  - lib/resque.rb
131
173
  - lib/resque/data_store.rb
132
174
  - lib/resque/errors.rb
@@ -186,7 +228,6 @@ licenses:
186
228
  metadata:
187
229
  changelog_uri: https://github.com/resque/resque/blob/master/HISTORY.md
188
230
  rubygems_mfa_required: 'true'
189
- post_install_message:
190
231
  rdoc_options:
191
232
  - "--charset=UTF-8"
192
233
  require_paths:
@@ -195,15 +236,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
195
236
  requirements:
196
237
  - - ">="
197
238
  - !ruby/object:Gem::Version
198
- version: 2.3.0
239
+ version: 3.0.0
199
240
  required_rubygems_version: !ruby/object:Gem::Requirement
200
241
  requirements:
201
242
  - - ">="
202
243
  - !ruby/object:Gem::Version
203
244
  version: '0'
204
245
  requirements: []
205
- rubygems_version: 3.0.3.1
206
- signing_key:
246
+ rubygems_version: 4.0.6
207
247
  specification_version: 4
208
248
  summary: Resque is a Redis-backed queueing system.
209
249
  test_files: []