sidekiq 8.1.3 → 8.1.4
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 +4 -4
- data/Changes.md +6 -0
- data/lib/sidekiq/api.rb +64 -0
- data/lib/sidekiq/cli.rb +1 -2
- data/lib/sidekiq/client.rb +5 -0
- data/lib/sidekiq/job.rb +13 -0
- data/lib/sidekiq/tui/tabs/base_tab.rb +20 -3
- data/lib/sidekiq/tui.rb +2 -0
- data/lib/sidekiq/version.rb +1 -1
- data/lib/sidekiq/web/application.rb +4 -0
- data/lib/sidekiq/web/helpers.rb +1 -0
- data/web/locales/gd.yml +11 -1
- data/web/views/_job_info.html.erb +8 -0
- data/web/views/busy.html.erb +6 -1
- data/web/views/retries.html.erb +3 -0
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 44df206459c8280090bcf339baa35fbd6ff2ed2dee6ade615e71caed68e34c77
|
|
4
|
+
data.tar.gz: c3e3238d59e0150d5ab67edf02c4a73eae7b7dfd3a19b72db7354ea4ef8b677c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b6d89797767ce01eb6dc86ca8dc88edb96e66c3b407ba66309228ed81b993dfeaf31bf0dd9c00f1a8a26320e983006629330d28101d9a2c735df4897062bccad
|
|
7
|
+
data.tar.gz: a027b597b9b3446555fdf37d6ec0ec35edb208815c73500febbd3f914dcda4da633aa3c05ce678fa90ed25244bcd0b189ad2adab0b733a131f7f14b4a1463ce1
|
data/Changes.md
CHANGED
|
@@ -2,6 +2,12 @@
|
|
|
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.4
|
|
6
|
+
----------
|
|
7
|
+
|
|
8
|
+
- The TTIN signal is undeprecated as the INFO signal is not supported on Linux
|
|
9
|
+
- Show iteration job state on Busy page [#6978]
|
|
10
|
+
|
|
5
11
|
8.1.3
|
|
6
12
|
----------
|
|
7
13
|
|
data/lib/sidekiq/api.rb
CHANGED
|
@@ -478,6 +478,10 @@ module Sidekiq
|
|
|
478
478
|
self["jid"]
|
|
479
479
|
end
|
|
480
480
|
|
|
481
|
+
def iterable_state
|
|
482
|
+
@iterable_state ||= Sidekiq::IterableJobQuery.new(jid)[jid]
|
|
483
|
+
end
|
|
484
|
+
|
|
481
485
|
def bid
|
|
482
486
|
self["bid"]
|
|
483
487
|
end
|
|
@@ -1397,6 +1401,66 @@ module Sidekiq
|
|
|
1397
1401
|
Sidekiq.redis { |c| c.hget(key, "data") }
|
|
1398
1402
|
end
|
|
1399
1403
|
end
|
|
1404
|
+
|
|
1405
|
+
# Persisted iteration state from Redis for jobs using Sidekiq::IterableJob.
|
|
1406
|
+
class IterableJobQuery
|
|
1407
|
+
def initialize(jids)
|
|
1408
|
+
@cache = bulk_fetch(jids)
|
|
1409
|
+
end
|
|
1410
|
+
|
|
1411
|
+
def [](jid)
|
|
1412
|
+
@cache[jid]
|
|
1413
|
+
end
|
|
1414
|
+
|
|
1415
|
+
private
|
|
1416
|
+
|
|
1417
|
+
# Bulk-fetch iteration state for multiple JIDs in a single Redis pipeline.
|
|
1418
|
+
# Returns a Hash of { jid => IterableJobState } for JIDs that have iteration state.
|
|
1419
|
+
def bulk_fetch(jids)
|
|
1420
|
+
raise ArgumentError unless jids
|
|
1421
|
+
jids_to_fetch = Array(jids).compact.uniq
|
|
1422
|
+
return {} if jids_to_fetch.empty?
|
|
1423
|
+
|
|
1424
|
+
results = Sidekiq.redis do |conn|
|
|
1425
|
+
conn.pipelined do |pipe|
|
|
1426
|
+
jids_to_fetch.each { |jid| pipe.hgetall("it-#{jid}") }
|
|
1427
|
+
end
|
|
1428
|
+
end
|
|
1429
|
+
|
|
1430
|
+
# TODO Requires Ruby 4
|
|
1431
|
+
# states = ::Hash.new(capacity: jids_to_fetch.size)
|
|
1432
|
+
states = {}
|
|
1433
|
+
jids_to_fetch.each_with_index do |jid, i|
|
|
1434
|
+
raw = results[i]
|
|
1435
|
+
next if raw.nil? || raw.empty?
|
|
1436
|
+
|
|
1437
|
+
states[jid] = State.new(jid, raw)
|
|
1438
|
+
end
|
|
1439
|
+
states
|
|
1440
|
+
end
|
|
1441
|
+
|
|
1442
|
+
State = Struct.new(:jid, :raw) do
|
|
1443
|
+
def executions
|
|
1444
|
+
raw["ex"].to_i
|
|
1445
|
+
end
|
|
1446
|
+
|
|
1447
|
+
def runtime
|
|
1448
|
+
raw["rt"].to_f
|
|
1449
|
+
end
|
|
1450
|
+
|
|
1451
|
+
def cursor
|
|
1452
|
+
@cursor ||= begin
|
|
1453
|
+
Sidekiq.load_json(raw["c"])
|
|
1454
|
+
rescue JSON::ParserError
|
|
1455
|
+
@raw["c"]
|
|
1456
|
+
end
|
|
1457
|
+
end
|
|
1458
|
+
|
|
1459
|
+
def cancelled
|
|
1460
|
+
raw["cancelled"]&.to_i
|
|
1461
|
+
end
|
|
1462
|
+
end
|
|
1463
|
+
end
|
|
1400
1464
|
end
|
|
1401
1465
|
|
|
1402
1466
|
Sidekiq.loader.run_load_hooks(:api)
|
data/lib/sidekiq/cli.rb
CHANGED
|
@@ -200,9 +200,7 @@ module Sidekiq # :nodoc:
|
|
|
200
200
|
cli.logger.info "Received TSTP, no longer accepting new work"
|
|
201
201
|
cli.launcher.quiet
|
|
202
202
|
},
|
|
203
|
-
# deprecated, use INFO
|
|
204
203
|
"TTIN" => ->(cli) {
|
|
205
|
-
cli.logger.error { "DEPRECATED: Please use the INFO signal for backtraces, support for TTIN will be removed in Sidekiq 9.0." }
|
|
206
204
|
Thread.list.each do |thread|
|
|
207
205
|
cli.logger.warn "Thread TID-#{(thread.object_id ^ ::Process.pid).to_s(36)} #{thread.name}"
|
|
208
206
|
if thread.backtrace
|
|
@@ -213,6 +211,7 @@ module Sidekiq # :nodoc:
|
|
|
213
211
|
end
|
|
214
212
|
},
|
|
215
213
|
"INFO" => ->(cli) {
|
|
214
|
+
cli.logger.error { "DEPRECATED: the INFO signal does not work on Linux, use TTIN instead." }
|
|
216
215
|
Thread.list.each do |thread|
|
|
217
216
|
cli.logger.warn "Thread TID-#{(thread.object_id ^ ::Process.pid).to_s(36)} #{thread.name}"
|
|
218
217
|
if thread.backtrace
|
data/lib/sidekiq/client.rb
CHANGED
|
@@ -117,6 +117,11 @@ module Sidekiq
|
|
|
117
117
|
# larger than 1000 but YMMV based on network quality, size of job args, etc.
|
|
118
118
|
# A large number of jobs can cause a bit of Redis command processing latency.
|
|
119
119
|
#
|
|
120
|
+
# Accepts an `:at` option to schedule the jobs for future execution. It
|
|
121
|
+
# accepts either a single Numeric timestamp (or seconds-from-now) applied
|
|
122
|
+
# to every job, or an Array of Numeric values with the same size as `args`
|
|
123
|
+
# to schedule each job at its corresponding time.
|
|
124
|
+
#
|
|
120
125
|
# Accepts an additional `:spread_interval` option (in seconds) to randomly spread
|
|
121
126
|
# the jobs schedule times over the specified interval.
|
|
122
127
|
#
|
data/lib/sidekiq/job.rb
CHANGED
|
@@ -313,6 +313,11 @@ module Sidekiq
|
|
|
313
313
|
#
|
|
314
314
|
# +items+ must be an Array of Arrays.
|
|
315
315
|
#
|
|
316
|
+
# The +:at+ option schedules the jobs for future execution. It accepts
|
|
317
|
+
# either a single Numeric timestamp (or seconds-from-now) applied to every
|
|
318
|
+
# job, or an Array of Numeric values with the same size as +items+ to
|
|
319
|
+
# schedule each job at its corresponding time.
|
|
320
|
+
#
|
|
316
321
|
# For finer-grained control, use `Sidekiq::Client.push_bulk` directly.
|
|
317
322
|
#
|
|
318
323
|
# Example (3 Redis round trips):
|
|
@@ -325,6 +330,14 @@ module Sidekiq
|
|
|
325
330
|
#
|
|
326
331
|
# SomeJob.perform_bulk([[1], [2], [3]])
|
|
327
332
|
#
|
|
333
|
+
# Scheduling every job 60 seconds from now (single Numeric +:at+):
|
|
334
|
+
#
|
|
335
|
+
# SomeJob.perform_bulk([[1], [2], [3]], at: 60)
|
|
336
|
+
#
|
|
337
|
+
# Scheduling each job at its own time (Array +:at+):
|
|
338
|
+
#
|
|
339
|
+
# SomeJob.perform_bulk([[1], [2]], at: [Time.now.to_f + 30, Time.now.to_f + 60])
|
|
340
|
+
#
|
|
328
341
|
def perform_bulk(*args, **kwargs)
|
|
329
342
|
Setter.new(self, {}).perform_bulk(*args, **kwargs)
|
|
330
343
|
end
|
|
@@ -154,7 +154,7 @@ module Sidekiq
|
|
|
154
154
|
|
|
155
155
|
# Format keys and values with spacing
|
|
156
156
|
keys_line = keys.map { |k| t(k).to_s.ljust(12) }.join(" ")
|
|
157
|
-
values_line = values.map { |v| v.
|
|
157
|
+
values_line = values.map { |v| number_with_delimiter(v).ljust(12) }.join(" ")
|
|
158
158
|
|
|
159
159
|
frame.render_widget(
|
|
160
160
|
tui.paragraph(
|
|
@@ -165,10 +165,27 @@ module Sidekiq
|
|
|
165
165
|
)
|
|
166
166
|
end
|
|
167
167
|
|
|
168
|
-
#
|
|
168
|
+
# [thousands_separator, decimal_separator] per locale.
|
|
169
|
+
# Locales not listed here use the English default [",", "."].
|
|
170
|
+
NUMERIC_SEPARATORS = {
|
|
171
|
+
# period thousands, comma decimal
|
|
172
|
+
"da" => [".", ","], "de" => [".", ","], "el" => [".", ","],
|
|
173
|
+
"es" => [".", ","], "it" => [".", ","], "nl" => [".", ","],
|
|
174
|
+
"pt" => [".", ","], "pt-BR" => [".", ","], "tr" => [".", ","],
|
|
175
|
+
"vi" => [".", ","],
|
|
176
|
+
# space thousands, comma decimal
|
|
177
|
+
"cs" => [" ", ","], "fr" => [" ", ","], "lt" => [" ", ","],
|
|
178
|
+
"nb" => [" ", ","], "pl" => [" ", ","], "ru" => [" ", ","],
|
|
179
|
+
"sv" => [" ", ","], "uk" => [" ", ","]
|
|
180
|
+
}.freeze
|
|
181
|
+
|
|
169
182
|
def number_with_delimiter(number, options = {})
|
|
170
183
|
precision = options[:precision] || 0
|
|
171
|
-
number.round(precision)
|
|
184
|
+
rounded = number.round(precision)
|
|
185
|
+
thousands, decimal = NUMERIC_SEPARATORS.fetch(@parent.lang, [",", "."])
|
|
186
|
+
integer_part, decimal_part = rounded.to_s.split(".")
|
|
187
|
+
integer_with_sep = integer_part.gsub(/(\d)(?=(\d{3})+(?!\d))/, "\\1#{thousands}")
|
|
188
|
+
(precision > 0) ? "#{integer_with_sep}#{decimal}#{(decimal_part || "").ljust(precision, "0")}" : integer_with_sep
|
|
172
189
|
end
|
|
173
190
|
|
|
174
191
|
def format_memory(rss_kb)
|
data/lib/sidekiq/tui.rb
CHANGED
|
@@ -21,6 +21,8 @@ module Sidekiq
|
|
|
21
21
|
REFRESH_INTERVAL_SECONDS = 2
|
|
22
22
|
LOCALE_DIRECTORIES = [File.expand_path("#{File.dirname(__FILE__)}/../../web/locales")]
|
|
23
23
|
|
|
24
|
+
attr_reader :lang
|
|
25
|
+
|
|
24
26
|
# language is meant to be a locale code, e.g.
|
|
25
27
|
# LANG=en_US.utf-8
|
|
26
28
|
def initialize(cfg, language: ENV["LANG"] || "en")
|
data/lib/sidekiq/version.rb
CHANGED
|
@@ -92,6 +92,8 @@ module Sidekiq
|
|
|
92
92
|
@count = (url_params("count") || 100).to_i
|
|
93
93
|
(@current_page, @total_size, @workset) = page_items(workset, url_params("page"), @count)
|
|
94
94
|
|
|
95
|
+
@iterable_states = Sidekiq::IterableJobQuery.new(workset.map { |_, _, work| work.job.jid })
|
|
96
|
+
|
|
95
97
|
erb(:busy)
|
|
96
98
|
end
|
|
97
99
|
|
|
@@ -226,6 +228,8 @@ module Sidekiq
|
|
|
226
228
|
@retries = @retries.map { |msg, score| Sidekiq::SortedEntry.new(nil, score, msg) }
|
|
227
229
|
end
|
|
228
230
|
|
|
231
|
+
@iterable_states = Sidekiq::IterableJobQuery.new(@retries.map(&:jid))
|
|
232
|
+
|
|
229
233
|
erb(:retries)
|
|
230
234
|
end
|
|
231
235
|
|
data/lib/sidekiq/web/helpers.rb
CHANGED
data/web/locales/gd.yml
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# elements like %{queue} are variables and should not be translated
|
|
2
2
|
gd:
|
|
3
|
-
LanguageName:
|
|
3
|
+
LanguageName: Gàidhlig
|
|
4
4
|
Actions: Gnìomhan
|
|
5
5
|
AddToQueue: Cuir ris a’ chiutha
|
|
6
6
|
AddAllToQueue: Cuir a h-uile ris a’ chiutha
|
|
@@ -36,6 +36,8 @@ gd:
|
|
|
36
36
|
Jobs: Obraichean
|
|
37
37
|
Kill: Marbh
|
|
38
38
|
KillAll: Marbh na h-uile
|
|
39
|
+
Language: Cànan
|
|
40
|
+
LastDashboardUpdateTemplateLiteral: "An t-ath-nuadhachadh mu dheireadh: Air pròiseasadh: PROCESSED_COUNT. Air fàilligeadh: FAILED_COUNT."
|
|
39
41
|
LastRetry: An oidhirp mu dheireadh
|
|
40
42
|
Latency: Foillidheachd
|
|
41
43
|
LivePoll: Ath-nuadhachadh beò
|
|
@@ -55,6 +57,7 @@ gd:
|
|
|
55
57
|
PeakMemoryUsage: Bàrr cleachdadh a’ chuimhne
|
|
56
58
|
Plugins: Plugain
|
|
57
59
|
PollingInterval: Eadaramh an ath-nuadhachaidh
|
|
60
|
+
PollingIntervalMilliseconds: Milidiogan eadaramh an ath-nuadhachaidh
|
|
58
61
|
Process: Pròiseas
|
|
59
62
|
Processed: Air pròiseasadh
|
|
60
63
|
Processes: Pròiseasan
|
|
@@ -98,3 +101,10 @@ gd:
|
|
|
98
101
|
AvgExecutionTime: Ùine cuibheasach nan gnìomhan
|
|
99
102
|
Context: Co-theacsa
|
|
100
103
|
NoJobMetricsFound: Cha deach meatraigeachd o chionn goirid air obair a lorg
|
|
104
|
+
Filter: Criathraich
|
|
105
|
+
AnyJobContent: Susbaint obrach sam bith
|
|
106
|
+
Profiles: Pròifilean
|
|
107
|
+
Data: Dàta
|
|
108
|
+
View: Seall
|
|
109
|
+
Token: Tòcan
|
|
110
|
+
ElapsedTime: An ùine a chaidh seachad
|
|
@@ -34,6 +34,14 @@
|
|
|
34
34
|
<code><%= job.jid %></code>
|
|
35
35
|
</td>
|
|
36
36
|
</tr>
|
|
37
|
+
<% if (state = job.iterable_state) %>
|
|
38
|
+
<tr>
|
|
39
|
+
<th>Iteration</th>
|
|
40
|
+
<td>
|
|
41
|
+
<code>cursor=<%= h(state.cursor.inspect) %>; exec=<%= state.executions %>; rt=<%= number_with_delimiter(state.runtime, precision: 3) %>s</code>
|
|
42
|
+
</td>
|
|
43
|
+
</tr>
|
|
44
|
+
<% end %>
|
|
37
45
|
<% if job.bid %>
|
|
38
46
|
<tr>
|
|
39
47
|
<th>BID</th>
|
data/web/views/busy.html.erb
CHANGED
|
@@ -138,7 +138,12 @@
|
|
|
138
138
|
<td>
|
|
139
139
|
<code><div class="args"><%= display_args(job.display_args) %></div></code>
|
|
140
140
|
</td>
|
|
141
|
-
<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>
|
|
142
147
|
</tr>
|
|
143
148
|
<% end %>
|
|
144
149
|
</table>
|
data/web/views/retries.html.erb
CHANGED
|
@@ -52,6 +52,9 @@
|
|
|
52
52
|
</td>
|
|
53
53
|
<td>
|
|
54
54
|
<div><a href="<%= root_path %>retries/<%= job_params(entry.item, entry.score) %>"><%= h truncate("#{entry['error_class']}: #{entry['error_message']}", 200) %></a></div>
|
|
55
|
+
<% if (state = @iterable_states[entry.jid]) %>
|
|
56
|
+
<div><small>cursor=<%= h(truncate(state.cursor.inspect, 100)) %>; exec=<%= state.executions %>; rt=<%= number_with_delimiter(state.runtime, precision: 3) %>s</small></div>
|
|
57
|
+
<% end %>
|
|
55
58
|
</td>
|
|
56
59
|
</tr>
|
|
57
60
|
<% end %>
|