sidekiq 7.0.1 → 7.0.2

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of sidekiq might be problematic. Click here for more details.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 98aab60f0a9bd14122cf62b2f31c17e41b67feb8c9fb13865ef0a16002d38ed7
4
- data.tar.gz: 94038f0176ccb7785c6112cd41e915e4a1c7f66298a9670457a68e6b62f2710c
3
+ metadata.gz: 9456d6050f916f7777b11ff32528c3c872fefa5a4e7afa32773e030ca9b6df7e
4
+ data.tar.gz: 501ca5569b669bb5c5eaf80d4ae3c1c8cc20e7c51235cfc72abcb2d3b25bc6ea
5
5
  SHA512:
6
- metadata.gz: c41c724dc99aa3fdf49db46eeac0bec822bd6a67989792f4830900da7b74882c27837535a03a2ea6ed0575736fc895b23bb3440613d1f581e877bcbfe1c06934
7
- data.tar.gz: 482af09f25f72f9fa0261f02e4e224dc58a400519f167f8cb0ea0dda4960b24a41b105731a4fcc2b81ff15f158497b9bf1cc86d55272ed8fe4ca7ed9029bc047
6
+ metadata.gz: 0267fbbfbf028e4f9c091e28c31b4b18de6c795e32359c38cf2f09da7c2bc43654c1b3482443befbaada0715fdb591ae74037bed99069bd26db5fca961befec1
7
+ data.tar.gz: f2a5275b2fa2a47e1aa0b6d5a5009cc373dddd64f0226d481f575079fee6a91ebc8ddacfc96536085df9bae685bf45fd42660eecf656d07521033b921f8125ed
data/Changes.md CHANGED
@@ -2,6 +2,29 @@
2
2
 
3
3
  [Sidekiq Changes](https://github.com/mperham/sidekiq/blob/main/Changes.md) | [Sidekiq Pro Changes](https://github.com/mperham/sidekiq/blob/main/Pro-Changes.md) | [Sidekiq Enterprise Changes](https://github.com/mperham/sidekiq/blob/main/Ent-Changes.md)
4
4
 
5
+ 7.0.2
6
+ ----------
7
+
8
+ - Improve compatibility with custom loggers [#5673]
9
+ - Add queue weights on Busy page [#5640]
10
+ - Add BID link on job_info page if job is part of a Batch [#5623]
11
+ - Allow custom extensions to add rows/links within Job detail pages [#5624]
12
+ ```ruby
13
+ Sidekiq::Web.custom_job_info_rows << AddAccountLink.new
14
+
15
+ class AddAccountLink
16
+ include CGI::Util
17
+ def add_pair(job)
18
+ # yield a (name, value) pair
19
+ # You can include HTML tags and CSS, Sidekiq does not do any
20
+ # escaping so beware user data injection! Note how we use CGI's
21
+ # `h` escape helper.
22
+ aid = job["account_id"]
23
+ yield "Account", "<a href='/accounts/#{h aid}'>#{h aid}</a>" if aid
24
+ end
25
+ end
26
+ ```
27
+
5
28
  7.0.1
6
29
  ----------
7
30
 
data/lib/sidekiq/api.rb CHANGED
@@ -418,6 +418,10 @@ module Sidekiq
418
418
  self["jid"]
419
419
  end
420
420
 
421
+ def bid
422
+ self["bid"]
423
+ end
424
+
421
425
  def enqueued_at
422
426
  self["enqueued_at"] ? Time.at(self["enqueued_at"]).utc : nil
423
427
  end
@@ -967,6 +971,14 @@ module Sidekiq
967
971
  self["queues"]
968
972
  end
969
973
 
974
+ def weights
975
+ self["weights"]
976
+ end
977
+
978
+ def version
979
+ self["version"]
980
+ end
981
+
970
982
  # Signal this process to stop processing new jobs.
971
983
  # It will continue to execute jobs it has already fetched.
972
984
  # This method is *asynchronous* and it can take 5-10
@@ -189,7 +189,7 @@ module Sidekiq
189
189
  def enqueue_to_in(queue, interval, klass, *args)
190
190
  int = interval.to_f
191
191
  now = Time.now.to_f
192
- ts = (int < 1_000_000_000 ? now + int : int)
192
+ ts = ((int < 1_000_000_000) ? now + int : int)
193
193
 
194
194
  item = {"class" => klass, "args" => args, "at" => ts, "queue" => queue}
195
195
  item.delete("at") if ts <= now
@@ -134,7 +134,7 @@ module Sidekiq
134
134
 
135
135
  def redis_info
136
136
  redis do |conn|
137
- conn.info
137
+ conn.call("INFO") { |i| i.lines(chomp: true).map { |l| l.split(":", 2) }.select { |l| l.size == 2 }.to_h }
138
138
  rescue RedisClientAdapter::CommandError => ex
139
139
  # 2850 return fake version when INFO command has (probably) been renamed
140
140
  raise unless /unknown command/.match?(ex.message)
@@ -248,7 +248,6 @@ module Sidekiq
248
248
  return
249
249
  end
250
250
 
251
- logger.extend(Sidekiq::LoggingUtils)
252
251
  @logger = logger
253
252
  end
254
253
 
@@ -21,15 +21,15 @@ module Sidekiq
21
21
  }
22
22
 
23
23
  def self.mark!(label = nil)
24
- label ||= LABEL_MAKER.call
25
- Sidekiq::Deploy.new.mark(label: label)
24
+ Sidekiq::Deploy.new.mark!(label: label)
26
25
  end
27
26
 
28
27
  def initialize(pool = Sidekiq::RedisConnection.create)
29
28
  @pool = pool
30
29
  end
31
30
 
32
- def mark(at: Time.now, label: "")
31
+ def mark!(at: Time.now, label: nil)
32
+ label ||= LABEL_MAKER.call
33
33
  # we need to round the timestamp so that we gracefully
34
34
  # handle an very common error in marking deploys:
35
35
  # having every process mark its deploy, leading
data/lib/sidekiq/job.rb CHANGED
@@ -258,7 +258,7 @@ module Sidekiq
258
258
  def at(interval)
259
259
  int = interval.to_f
260
260
  now = Time.now.to_f
261
- ts = (int < 1_000_000_000 ? now + int : int)
261
+ ts = ((int < 1_000_000_000) ? now + int : int)
262
262
  # Optimization to enqueue something now that is scheduled to go out now or in the past
263
263
  @opts["at"] = ts if ts > now
264
264
  self
@@ -325,7 +325,7 @@ module Sidekiq
325
325
  def perform_in(interval, *args)
326
326
  int = interval.to_f
327
327
  now = Time.now.to_f
328
- ts = (int < 1_000_000_000 ? now + int : int)
328
+ ts = ((int < 1_000_000_000) ? now + int : int)
329
329
 
330
330
  item = {"class" => self, "args" => args}
331
331
 
@@ -33,7 +33,7 @@ module Sidekiq
33
33
 
34
34
  Thread.current[:sidekiq_context] = h
35
35
  level = job_hash["log_level"]
36
- if level
36
+ if level && @logger.respond_to?(:log_at)
37
37
  @logger.log_at(level, &block)
38
38
  else
39
39
  yield
@@ -250,9 +250,11 @@ module Sidekiq
250
250
  "pid" => ::Process.pid,
251
251
  "tag" => @config[:tag] || "",
252
252
  "concurrency" => @config.total_concurrency,
253
- "queues" => @config.capsules.values.map { |cap| cap.queues }.flatten.uniq,
253
+ "queues" => @config.capsules.values.flat_map { |cap| cap.queues }.uniq,
254
+ "weights" => @config.capsules.values.flat_map { |cap| cap.queues }.tally,
254
255
  "labels" => @config[:labels].to_a,
255
- "identity" => identity
256
+ "identity" => identity,
257
+ "version" => Sidekiq::VERSION
256
258
  }
257
259
  end
258
260
 
@@ -123,7 +123,7 @@ module Sidekiq
123
123
  def series_avg(metric = "ms")
124
124
  series[metric].each_with_object(Hash.new(0)) do |(bucket, value), result|
125
125
  completed = series.dig("p", bucket) - series.dig("f", bucket)
126
- result[bucket] = completed == 0 ? 0 : value.to_f / completed
126
+ result[bucket] = (completed == 0) ? 0 : value.to_f / completed
127
127
  end
128
128
  end
129
129
  end
@@ -49,10 +49,25 @@ class Sidekiq::Monitor
49
49
  def processes
50
50
  puts "---- Processes (#{process_set.size}) ----"
51
51
  process_set.each_with_index do |process, index|
52
+ # Keep compatibility with legacy versions since we don't want to break sidekiqmon during rolling upgrades or downgrades.
53
+ #
54
+ # Before:
55
+ # ["default", "critical"]
56
+ #
57
+ # After:
58
+ # {"default" => 1, "critical" => 10}
59
+ queues =
60
+ if process["weights"]
61
+ process["weights"].sort_by { |queue| queue[0] }.map { |queue| queue.join(": ") }
62
+ else
63
+ process["queues"].sort
64
+ end
65
+
52
66
  puts "#{process["identity"]} #{tags_for(process)}"
53
67
  puts " Started: #{Time.at(process["started_at"])} (#{time_ago(process["started_at"])})"
54
68
  puts " Threads: #{process["concurrency"]} (#{process["busy"]} busy)"
55
- puts " Queues: #{split_multiline(process["queues"].sort, pad: 11)}"
69
+ puts " Queues: #{split_multiline(queues, pad: 11)}"
70
+ puts " Version: #{process["version"] || "Unknown"}" if process["version"] != Sidekiq::VERSION
56
71
  puts "" unless (index + 1) == process_set.size
57
72
  end
58
73
  end
@@ -101,7 +116,7 @@ class Sidekiq::Monitor
101
116
  tags = [
102
117
  process["tag"],
103
118
  process["labels"],
104
- (process["quiet"] == "true" ? "quiet" : nil)
119
+ ((process["quiet"] == "true") ? "quiet" : nil)
105
120
  ].flatten.compact
106
121
  tags.any? ? "[#{tags.join("] [")}]" : nil
107
122
  end
@@ -3,7 +3,7 @@
3
3
  module Sidekiq
4
4
  module Paginator
5
5
  def page(key, pageidx = 1, page_size = 25, opts = nil)
6
- current_page = pageidx.to_i < 1 ? 1 : pageidx.to_i
6
+ current_page = (pageidx.to_i < 1) ? 1 : pageidx.to_i
7
7
  pageidx = current_page - 1
8
8
  total_size = 0
9
9
  items = []
@@ -45,7 +45,7 @@ module Sidekiq
45
45
  end
46
46
 
47
47
  def page_items(items, pageidx = 1, page_size = 25)
48
- current_page = pageidx.to_i < 1 ? 1 : pageidx.to_i
48
+ current_page = (pageidx.to_i < 1) ? 1 : pageidx.to_i
49
49
  pageidx = current_page - 1
50
50
  starting = pageidx * page_size
51
51
  items = items.to_a
@@ -9,10 +9,12 @@ module Sidekiq
9
9
  CommandError = RedisClient::CommandError
10
10
 
11
11
  module CompatMethods
12
+ # TODO Deprecate and remove this
12
13
  def info
13
14
  @client.call("INFO") { |i| i.lines(chomp: true).map { |l| l.split(":", 2) }.select { |l| l.size == 2 }.to_h }
14
15
  end
15
16
 
17
+ # TODO Deprecate and remove this
16
18
  def evalsha(sha, keys, argv)
17
19
  @client.call("EVALSHA", sha, keys.size, *keys, *argv)
18
20
  end
@@ -34,12 +36,7 @@ module Sidekiq
34
36
  CompatClient = RedisClient::Decorator.create(CompatMethods)
35
37
 
36
38
  class CompatClient
37
- # underscore methods are not official API
38
- def _client
39
- @client
40
- end
41
-
42
- def _config
39
+ def config
43
40
  @client.config
44
41
  end
45
42
 
@@ -54,7 +54,7 @@ module Sidekiq
54
54
  @lua_zpopbyscore_sha = conn.script(:load, LUA_ZPOPBYSCORE)
55
55
  end
56
56
 
57
- conn.evalsha(@lua_zpopbyscore_sha, keys, argv)
57
+ conn.call("EVALSHA", @lua_zpopbyscore_sha, keys.size, *keys, *argv)
58
58
  rescue RedisClient::CommandError => e
59
59
  raise unless e.message.start_with?("NOSCRIPT")
60
60
 
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Sidekiq
4
- VERSION = "7.0.1"
4
+ VERSION = "7.0.2"
5
5
  MAJOR = 7
6
6
  end
@@ -137,7 +137,7 @@ module Sidekiq
137
137
  end
138
138
 
139
139
  def sort_direction_label
140
- params[:direction] == "asc" ? "&uarr;" : "&darr;"
140
+ (params[:direction] == "asc") ? "&uarr;" : "&darr;"
141
141
  end
142
142
 
143
143
  def workset
@@ -167,7 +167,7 @@ module Sidekiq
167
167
 
168
168
  def redis_url
169
169
  Sidekiq.redis do |conn|
170
- conn._config.server_url
170
+ conn.config.server_url
171
171
  end
172
172
  end
173
173
 
@@ -184,7 +184,7 @@ module Sidekiq
184
184
  end
185
185
 
186
186
  def current_status
187
- workset.size == 0 ? "idle" : "active"
187
+ (workset.size == 0) ? "idle" : "active"
188
188
  end
189
189
 
190
190
  def relative_time(time)
@@ -217,7 +217,7 @@ module Sidekiq
217
217
  end
218
218
 
219
219
  def truncate(text, truncate_after_chars = 2000)
220
- truncate_after_chars && text.size > truncate_after_chars ? "#{text[0..truncate_after_chars]}..." : text
220
+ (truncate_after_chars && text.size > truncate_after_chars) ? "#{text[0..truncate_after_chars]}..." : text
221
221
  end
222
222
 
223
223
  def display_args(args, truncate_after_chars = 2000)
@@ -324,7 +324,7 @@ module Sidekiq
324
324
  end
325
325
 
326
326
  def pollable?
327
- !(current_path == "" || current_path.starts_with?("metrics"))
327
+ !(current_path == "" || current_path.start_with?("metrics"))
328
328
  end
329
329
 
330
330
  def retry_or_delete_or_kill(job, params)
data/lib/sidekiq/web.rb CHANGED
@@ -48,6 +48,10 @@ module Sidekiq
48
48
  end
49
49
  alias_method :tabs, :custom_tabs
50
50
 
51
+ def custom_job_info_rows
52
+ @custom_job_info_rows ||= []
53
+ end
54
+
51
55
  def locales
52
56
  @locales ||= LOCALES
53
57
  end
data/sidekiq.gemspec CHANGED
@@ -22,7 +22,7 @@ Gem::Specification.new do |gem|
22
22
  "source_code_uri" => "https://github.com/mperham/sidekiq"
23
23
  }
24
24
 
25
- gem.add_dependency "redis-client", ">= 0.9.0"
25
+ gem.add_dependency "redis-client", ">= 0.11.0"
26
26
  gem.add_dependency "connection_pool", ">= 2.3.0"
27
27
  gem.add_dependency "rack", ">= 2.2.4"
28
28
  gem.add_dependency "concurrent-ruby", "< 2"
@@ -31,6 +31,7 @@ function addListeners() {
31
31
  node.addEventListener("click", addDataToggleListeners)
32
32
  })
33
33
 
34
+ addShiftClickListeners()
34
35
  updateFuzzyTimes();
35
36
  setLivePollFromUrl();
36
37
 
@@ -71,6 +72,23 @@ function addDataToggleListeners(event) {
71
72
  }
72
73
  }
73
74
 
75
+ function addShiftClickListeners() {
76
+ let checkboxes = Array.from(document.querySelectorAll(".shift_clickable"));
77
+ let lastChecked = null;
78
+ checkboxes.forEach(checkbox => {
79
+ checkbox.addEventListener("click", (e) => {
80
+ if (e.shiftKey && lastChecked) {
81
+ let myIndex = checkboxes.indexOf(checkbox);
82
+ let lastIndex = checkboxes.indexOf(lastChecked);
83
+ let [min, max] = [myIndex, lastIndex].sort();
84
+ let newState = checkbox.checked;
85
+ checkboxes.slice(min, max).forEach(c => c.checked = newState);
86
+ }
87
+ lastChecked = checkbox;
88
+ });
89
+ });
90
+ }
91
+
74
92
  function updateFuzzyTimes() {
75
93
  var locale = document.body.getAttribute("data-locale");
76
94
  var parts = locale.split('-');
@@ -72,6 +72,10 @@ table {
72
72
  background-color: #31708f;
73
73
  }
74
74
 
75
+ .alert-warning {
76
+ background-color: #c47612;
77
+ }
78
+
75
79
  a:link, a:active, a:hover, a:visited {
76
80
  color: #ddd;
77
81
  }
@@ -676,8 +676,8 @@ div.interval-slider input {
676
676
  }
677
677
 
678
678
  .info-circle {
679
- color: #ccc;
680
- background-color: #000;
679
+ color: #333;
680
+ background-color: #ccc;
681
681
  border-radius: 50%;
682
682
  text-align: center;
683
683
  vertical-align: middle;
@@ -33,6 +33,14 @@
33
33
  <code><%= job.jid %></code>
34
34
  </td>
35
35
  </tr>
36
+ <% if job.bid %>
37
+ <tr>
38
+ <th>BID</th>
39
+ <td>
40
+ <a href="<%= root_path %>batches/<%= job.bid %>"><%= job.bid %>
41
+ </td>
42
+ </tr>
43
+ <% end %>
36
44
  <tr>
37
45
  <th><%= t('CreatedAt') %></th>
38
46
  <td><%= relative_time(job.created_at) %></td>
@@ -84,6 +92,14 @@
84
92
  <td><%= relative_time(job.at) if job['retry_count'] %></td>
85
93
  </tr>
86
94
  <% end %>
95
+ <% Sidekiq::Web.custom_job_info_rows.each do |helper| %>
96
+ <% helper.add_pair(job) do |name, value| %>
97
+ <tr>
98
+ <th><%= name %></th>
99
+ <td><%= value %></td>
100
+ </tr>
101
+ <% end %>
102
+ <% end %>
87
103
  </tbody>
88
104
  </table>
89
105
  </div>
data/web/views/busy.erb CHANGED
@@ -70,7 +70,20 @@
70
70
  <% end %>
71
71
  <br>
72
72
  <b><%= "#{t('Queues')}: " %></b>
73
- <%= process.queues.join(", ") %>
73
+ <% if process.weights %>
74
+ <%= process.weights.sort_by { |weight| weight[0] }.map { |weight| weight.join(": ") }.join(", ") %>
75
+ <% else %>
76
+ <%= process.queues.sort.join(", ") %>
77
+ <% end %>
78
+ <% if process.version != Sidekiq::VERSION %>
79
+ <br>
80
+ <b><%= "#{t('Version')}: " %></b>
81
+ <% if process.version %>
82
+ <%= process.version %>
83
+ <% else %>
84
+ <%= t('Unknown') %>
85
+ <% end %>
86
+ <% end %>
74
87
  </td>
75
88
  <td><%= relative_time(Time.at(process['started_at'])) %></td>
76
89
  <td><%= format_memory(process['rss'].to_i) %></td>
data/web/views/morgue.erb CHANGED
@@ -33,7 +33,7 @@
33
33
  <tr>
34
34
  <td class="table-checkbox">
35
35
  <label>
36
- <input type='checkbox' name='key[]' value='<%= job_params(entry.item, entry.score) %>' />
36
+ <input type='checkbox' name='key[]' value='<%= job_params(entry.item, entry.score) %>' class='shift_clickable' />
37
37
  </label>
38
38
  </td>
39
39
  <td>
@@ -34,7 +34,7 @@
34
34
  <tr>
35
35
  <td class="table-checkbox">
36
36
  <label>
37
- <input type='checkbox' name='key[]' value='<%= job_params(entry.item, entry.score) %>' />
37
+ <input type='checkbox' name='key[]' value='<%= job_params(entry.item, entry.score) %>' class='shift_clickable' />
38
38
  </label>
39
39
  </td>
40
40
  <td>
@@ -30,7 +30,7 @@
30
30
  <% @scheduled.each do |entry| %>
31
31
  <tr>
32
32
  <td>
33
- <input type='checkbox' name='key[]' value='<%= job_params(entry.item, entry.score) %>' />
33
+ <input type='checkbox' name='key[]' value='<%= job_params(entry.item, entry.score) %>' class='shift_clickable' />
34
34
  </td>
35
35
  <td>
36
36
  <a href="<%= root_path %>scheduled/<%= job_params(entry.item, entry.score) %>"><%= relative_time(entry.at) %></a>
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sidekiq
3
3
  version: !ruby/object:Gem::Version
4
- version: 7.0.1
4
+ version: 7.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mike Perham
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-11-04 00:00:00.000000000 Z
11
+ date: 2022-11-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: redis-client
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: 0.9.0
19
+ version: 0.11.0
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: 0.9.0
26
+ version: 0.11.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: connection_pool
29
29
  requirement: !ruby/object:Gem::Requirement