sidekiq 8.1.5 → 8.1.6

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: 11298be12e389dc2bc8c9f722b5bdff096650fae86bb8a234d506db413c93144
4
- data.tar.gz: 17c1713a8c54977b1de6b0de2e1399d0edd97c3c682a75b35dcb16411e2a21b8
3
+ metadata.gz: 1e36b05d6e25f174a0ff8b8a21b4c097a108e4ccf98af88a56ae767cfea1186a
4
+ data.tar.gz: c58b4f89a1466bac6c9de05cf5ea2aee0152ac42184946b4d1646c6938b351a8
5
5
  SHA512:
6
- metadata.gz: 7eae0c8716939b3eb127163df6aedbd5ca794ef23d3ec884cc8a7d790352318a1f5501b2f2b6ebb711a810cfaa6b5488541515e7192383f0e7b37681fe5f8bac
7
- data.tar.gz: d40a3594074bc5184a7de2fd63899607e6adee7fdf1d8ebf53058411e69029d63fa010c0eef6edab44902746f56bdcfe4b06aade7118d9bb450ab1dd48ed4833
6
+ metadata.gz: 3b8690078001bb93fc6e4fb8fe4d52091d89c317d8dcef56d24247882f4c85dbe986a05ae5451aaf70b9ff25c4acbc89b2d15e909763550bbcb13f36e73b2f7f
7
+ data.tar.gz: 3cabd5a3a2861af5faf70c5f67d8eb93c578d58cb7825dc063e350f30ef37dc3e2c51060a58dcf2fca9915df1bb7fcbfd00d81996ba651c29882c8432545b03a
data/Changes.md CHANGED
@@ -2,9 +2,18 @@
2
2
 
3
3
  [Sidekiq Changes](https://github.com/sidekiq/sidekiq/blob/main/Changes.md) | [Sidekiq Pro Changes](https://github.com/sidekiq/sidekiq/blob/main/Pro-Changes.md) | [Sidekiq Enterprise Changes](https://github.com/sidekiq/sidekiq/blob/main/Ent-Changes.md)
4
4
 
5
+ 8.1.6
6
+ ----------
7
+
8
+ - Fix reported thread/memory leak when jobs fail [#7006]
9
+ - Users can limit data displayed on Busy page with the `only` parameter `/busy?only=(jobs|processes)` [#6992]
10
+ - Replace Rack::Utils usage with standard library APIs
11
+ - Several minor fixes from AI scanners.
12
+
5
13
  8.1.5
6
14
  ----------
7
15
 
16
+ - Fix sub-second precision when computing the `retry_for` deadline [#7003]
8
17
  - Identify Sidekiq connnections in Redis with `CLIENT SETINFO` [#6986]
9
18
  - Fix edge case where Web UI could show an empty Batch set [#6987]
10
19
 
@@ -47,6 +56,7 @@ Use REDIS_URL or REDIS_PROVIDER to point `kiq` to Redis.
47
56
  require "sidekiq/testing"
48
57
  require "sidekiq/testing/inline"
49
58
  # New, more explicit
59
+ require "sidekiq"
50
60
  Sidekiq.testing!(:fake)
51
61
  Sidekiq.testing!(:inline)
52
62
  ```
@@ -297,15 +297,11 @@ module Sidekiq
297
297
  @logger = logger
298
298
  end
299
299
 
300
- private def parameter_size(handler)
301
- target = handler.is_a?(Proc) ? handler : handler.method(:call)
302
- target.parameters.size
303
- end
304
-
305
300
  # INTERNAL USE ONLY
306
301
  def handle_exception(ex, ctx = {})
307
- if @options[:error_handlers].size == 0
308
- p ["!!!!!", ex]
302
+ if @options[:error_handlers].empty?
303
+ logger.error { "No error handlers configured, logging exception directly" }
304
+ logger.error { ex }
309
305
  end
310
306
  @options[:error_handlers].each do |handler|
311
307
  handler.call(ex, ctx, self)
data/lib/sidekiq/job.rb CHANGED
@@ -196,7 +196,7 @@ module Sidekiq
196
196
 
197
197
  def set(options)
198
198
  hash = options.transform_keys(&:to_s)
199
- interval = hash.delete("wait_until") || @opts.delete("wait")
199
+ interval = hash.delete("wait_until") || hash.delete("wait")
200
200
  @opts.merge!(hash)
201
201
  at(interval) if interval
202
202
  self
@@ -211,7 +211,7 @@ module Sidekiq
211
211
  if item.is_a?(Float)
212
212
  Time.at(item)
213
213
  else
214
- Time.at(item / 1000, item % 1000)
214
+ Time.at(item / 1000, item % 1000, :millisecond)
215
215
  end
216
216
  end
217
217
 
@@ -75,6 +75,7 @@ module Sidekiq
75
75
  p.start
76
76
  end
77
77
  end
78
+ nil
78
79
  end
79
80
 
80
81
  def stopped?
@@ -41,8 +41,8 @@ module Sidekiq
41
41
  # this allows us to use methods like `conn.hmset(...)` instead of having to use
42
42
  # redis-client's native `conn.call("hmset", ...)`
43
43
  def method_missing(*args, &block)
44
- warn("[sidekiq#5788] Redis has deprecated the `#{args.first}`command, called at #{caller(1..1)}") if DEPRECATED_COMMANDS.include?(args.first)
45
- @client.call(*args, *block)
44
+ warn("[sidekiq#5788] Redis has deprecated the `#{args.first}` command, called at #{caller(1..1)}") if DEPRECATED_COMMANDS.include?(args.first)
45
+ @client.call(*args, &block)
46
46
  end
47
47
  ruby2_keywords :method_missing if respond_to?(:ruby2_keywords, true)
48
48
 
@@ -1,2 +1,3 @@
1
+ require "sidekiq"
1
2
  Sidekiq.testing!(:fake)
2
3
  warn('⛔️ `require "sidekiq/testing"` is deprecated and will be removed in Sidekiq 9.0. See https://sidekiq.org/wiki/Testing#new-api')
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Sidekiq
4
- VERSION = "8.1.5"
4
+ VERSION = "8.1.6"
5
5
  MAJOR = 8
6
6
 
7
7
  def self.gem_version
@@ -24,8 +24,8 @@ module Sidekiq
24
24
  @request ||= ::Rack::Request.new(env)
25
25
  end
26
26
 
27
- def halt(res)
28
- throw :halt, [res, {"content-type" => "text/plain"}, [res.to_s]]
27
+ def halt(res, msg = nil)
28
+ throw :halt, [res, {"content-type" => "text/plain"}, [msg || res.to_s]]
29
29
  end
30
30
 
31
31
  # external redirect
@@ -90,9 +90,18 @@ module Sidekiq
90
90
 
91
91
  get "/busy" do
92
92
  @count = (url_params("count") || 100).to_i
93
- (@current_page, @total_size, @workset) = page_items(workset, url_params("page"), @count)
94
93
 
95
- @iterable_states = Sidekiq::IterableJobQuery.new(workset.map { |_, _, work| work.job.jid })
94
+ # Use /busy?only=(jobs|processes) to limit page data
95
+ only = url_params("only")
96
+ halt 401, "Invalid value for only" unless only.nil? || only == "jobs" || only == "processes"
97
+
98
+ @show_jobs = (only != "processes")
99
+ @show_processes = (only != "jobs")
100
+
101
+ if @show_jobs
102
+ (@current_page, @total_size, @workset) = page_items(workset, url_params("page"), @count)
103
+ @iterable_states = Sidekiq::IterableJobQuery.new(workset.map { |_, _, work| work.job.jid })
104
+ end
96
105
 
97
106
  erb(:busy)
98
107
  end
@@ -72,19 +72,13 @@ module Sidekiq
72
72
  # so extensions can be localized
73
73
  @@strings[lang] ||= config.locales.each_with_object({}) do |path, global|
74
74
  find_locale_files(lang).each do |file|
75
- strs = parse_yaml_new(file)
75
+ strs = parse_yaml(file)
76
76
  global.merge!(strs[lang])
77
77
  end
78
78
  end
79
79
  end
80
80
 
81
- # TODO Remove
82
- def parse_yaml_old(path)
83
- require "yaml"
84
- YAML.safe_load_file(path)
85
- end
86
-
87
- def parse_yaml_new(path)
81
+ def parse_yaml(path)
88
82
  locale = nil
89
83
  map = {}
90
84
  IO.readlines(path, chomp: true).each do |line|
@@ -156,17 +150,18 @@ module Sidekiq
156
150
  erb(:filtering, locals: {which:, placeholder_key:, label_key:})
157
151
  end
158
152
 
159
- def filter_link(jid, within = "retries")
153
+ def filter_link(str, within = "retries")
154
+ hstr = h(str)
160
155
  if within.nil?
161
- ::Rack::Utils.escape_html(jid)
156
+ hstr
162
157
  else
163
- "<a href='#{root_path}#{within}?substr=#{jid}'>#{::Rack::Utils.escape_html(jid)}</a>"
158
+ "<a href='#{root_path}#{within}?substr=#{hstr}'>#{hstr}</a>"
164
159
  end
165
160
  end
166
161
 
167
162
  def display_tags(job, within = "retries")
168
163
  job.tags.map { |tag|
169
- "<span class='label label-info jobtag jobtag-#{Rack::Utils.escape_html(tag)}'>#{filter_link(tag, within)}</span>"
164
+ "<span class='label label-info jobtag jobtag-#{h(tag)}'>#{filter_link(tag, within)}</span>"
170
165
  }.join(" ")
171
166
  end
172
167
 
@@ -337,7 +332,7 @@ module Sidekiq
337
332
  [score.to_f, jid]
338
333
  end
339
334
 
340
- SAFE_QPARAMS = %w[page direction]
335
+ SAFE_QPARAMS = %w[page direction only]
341
336
 
342
337
  # Merge options with current params, filter safe params, and stringify to query string
343
338
  def qparams(options)
@@ -420,7 +415,7 @@ module Sidekiq
420
415
  end
421
416
 
422
417
  def h(text)
423
- ::Rack::Utils.escape_html(text.to_s)
418
+ ::CGI.escapeHTML(text.to_s)
424
419
  rescue ArgumentError => e
425
420
  raise unless e.message.eql?("invalid byte sequence in UTF-8")
426
421
  text.encode!("UTF-16", "UTF-8", invalid: :replace, replace: "").encode!("UTF-8", "UTF-16")
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "rack"
3
+ require "uri"
4
4
 
5
5
  module Sidekiq
6
6
  class Web
@@ -28,7 +28,7 @@ module Sidekiq
28
28
 
29
29
  def match(env)
30
30
  request_method = env["REQUEST_METHOD"].downcase.to_sym
31
- path_info = ::Rack::Utils.unescape_path env["PATH_INFO"]
31
+ path_info = ::URI::RFC2396_PARSER.unescape env["PATH_INFO"]
32
32
 
33
33
  # There are servers which send an empty string when requesting the root.
34
34
  # These servers should be ashamed of themselves.
@@ -27,6 +27,7 @@
27
27
  </div>
28
28
  </section>
29
29
 
30
+ <% if @show_processes %>
30
31
  <section>
31
32
  <header>
32
33
  <h2><%= t('Processes') %></h2>
@@ -102,50 +103,53 @@
102
103
  </table>
103
104
  </div>
104
105
  </section>
106
+ <% end %>
105
107
 
106
- <section>
107
- <header>
108
- <h2><%= t('Jobs') %></h2>
109
- <% if @workset.size > 0 && @total_size > @count %>
110
- <%= erb :_paging, locals: { url: "#{root_path}busy" } %>
111
- <% end %>
112
- </header>
113
-
114
- <div class="table_container">
115
- <table>
116
- <thead>
117
- <th><%= t('Process') %></th>
118
- <th><%= t('TID') %></th>
119
- <th><%= t('JID') %></th>
120
- <th><%= t('Queue') %></th>
121
- <th><%= t('Job') %></th>
122
- <th><%= t('Arguments') %></th>
123
- <th><%= t('Started') %></th>
124
- </thead>
125
- <% @workset.each do |process, thread, work| %>
126
- <% job = work.job %>
127
- <tr>
128
- <td><%= process %></td>
129
- <td><%= thread %></td>
130
- <td><%= job.jid %></td>
131
- <td>
132
- <a href="<%= root_path %>queues/<%= work.queue %>"><%= work.queue %></a>
133
- </td>
134
- <td>
135
- <%= job.display_class %>
136
- <%= display_tags(job, nil) %>
137
- </td>
138
- <td>
139
- <code><div class="args"><%= display_args(job.display_args) %></div></code>
140
- </td>
141
- <td>
142
- <%= relative_time(work.run_at) %>
143
- <% if (state = @iterable_states[job.jid]) %>
144
- <div><small>cursor=<%= h(truncate(state.cursor.inspect, 100)) %>; exec=<%= state.executions %>; rt=<%= number_with_delimiter(state.runtime, precision: 3) %>s</small></div>
145
- <% end %>
146
- </td>
147
- </tr>
108
+ <% if @show_jobs %>
109
+ <section>
110
+ <header>
111
+ <h2><%= t('Jobs') %></h2>
112
+ <% if @workset.size > 0 && @total_size > @count %>
113
+ <%= erb :_paging, locals: { url: "#{root_path}busy" } %>
148
114
  <% end %>
149
- </table>
150
- </div>
151
- </section>
115
+ </header>
116
+
117
+ <div class="table_container">
118
+ <table>
119
+ <thead>
120
+ <th><%= t('Process') %></th>
121
+ <th><%= t('TID') %></th>
122
+ <th><%= t('JID') %></th>
123
+ <th><%= t('Queue') %></th>
124
+ <th><%= t('Job') %></th>
125
+ <th><%= t('Arguments') %></th>
126
+ <th><%= t('Started') %></th>
127
+ </thead>
128
+ <% @workset.each do |process, thread, work| %>
129
+ <% job = work.job %>
130
+ <tr>
131
+ <td><%= process %></td>
132
+ <td><%= thread %></td>
133
+ <td><%= job.jid %></td>
134
+ <td>
135
+ <a href="<%= root_path %>queues/<%= work.queue %>"><%= work.queue %></a>
136
+ </td>
137
+ <td>
138
+ <%= job.display_class %>
139
+ <%= display_tags(job, nil) %>
140
+ </td>
141
+ <td>
142
+ <code><div class="args"><%= display_args(job.display_args) %></div></code>
143
+ </td>
144
+ <td>
145
+ <%= relative_time(work.run_at) %>
146
+ <% if (state = @iterable_states[job.jid]) %>
147
+ <div><small>cursor=<%= h(truncate(state.cursor.inspect, 100)) %>; exec=<%= state.executions %>; rt=<%= number_with_delimiter(state.runtime, precision: 3) %>s</small></div>
148
+ <% end %>
149
+ </td>
150
+ </tr>
151
+ <% end %>
152
+ </table>
153
+ </div>
154
+ </section>
155
+ <% end %>
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sidekiq
3
3
  version: !ruby/object:Gem::Version
4
- version: 8.1.5
4
+ version: 8.1.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mike Perham