sidekiq 7.1.6 → 7.2.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/Changes.md +68 -0
  3. data/README.md +2 -2
  4. data/bin/multi_queue_bench +271 -0
  5. data/lib/sidekiq/api.rb +77 -11
  6. data/lib/sidekiq/cli.rb +3 -1
  7. data/lib/sidekiq/config.rb +4 -4
  8. data/lib/sidekiq/deploy.rb +2 -2
  9. data/lib/sidekiq/job.rb +1 -1
  10. data/lib/sidekiq/job_retry.rb +3 -3
  11. data/lib/sidekiq/launcher.rb +6 -4
  12. data/lib/sidekiq/logger.rb +1 -1
  13. data/lib/sidekiq/metrics/query.rb +4 -1
  14. data/lib/sidekiq/metrics/tracking.rb +7 -3
  15. data/lib/sidekiq/middleware/current_attributes.rb +1 -1
  16. data/lib/sidekiq/paginator.rb +2 -2
  17. data/lib/sidekiq/processor.rb +1 -1
  18. data/lib/sidekiq/rails.rb +7 -3
  19. data/lib/sidekiq/redis_client_adapter.rb +16 -0
  20. data/lib/sidekiq/redis_connection.rb +3 -6
  21. data/lib/sidekiq/scheduled.rb +2 -2
  22. data/lib/sidekiq/testing.rb +9 -3
  23. data/lib/sidekiq/transaction_aware_client.rb +7 -0
  24. data/lib/sidekiq/version.rb +1 -1
  25. data/lib/sidekiq/web/action.rb +5 -0
  26. data/lib/sidekiq/web/application.rb +32 -4
  27. data/lib/sidekiq/web/csrf_protection.rb +8 -5
  28. data/lib/sidekiq/web/helpers.rb +14 -15
  29. data/sidekiq.gemspec +1 -1
  30. data/web/assets/javascripts/application.js +21 -0
  31. data/web/assets/javascripts/dashboard-charts.js +14 -0
  32. data/web/assets/javascripts/dashboard.js +7 -9
  33. data/web/assets/javascripts/metrics.js +34 -0
  34. data/web/assets/stylesheets/application-rtl.css +10 -0
  35. data/web/assets/stylesheets/application.css +22 -0
  36. data/web/views/_footer.erb +13 -1
  37. data/web/views/_metrics_period_select.erb +1 -1
  38. data/web/views/_summary.erb +7 -7
  39. data/web/views/busy.erb +7 -7
  40. data/web/views/dashboard.erb +23 -33
  41. data/web/views/filtering.erb +4 -4
  42. data/web/views/metrics.erb +36 -27
  43. data/web/views/metrics_for_job.erb +26 -35
  44. data/web/views/queues.erb +6 -2
  45. metadata +5 -4
@@ -1,39 +1,39 @@
1
1
  <ul class="list-unstyled summary row">
2
2
  <li class="processed col-sm-1">
3
- <span id="txtProcessed" class="count"><%= number_with_delimiter(stats.processed) %></span>
3
+ <span id="txtProcessed" class="count" data-nwp><%= stats.processed %></span>
4
4
  <span class="desc"><%= t('Processed') %></span>
5
5
  </li>
6
6
  <li class="failed col-sm-1">
7
- <span id="txtFailed" class="count"><%= number_with_delimiter(stats.failed) %></span>
7
+ <span id="txtFailed" class="count" data-nwp><%= stats.failed %></span>
8
8
  <span class="desc"><%= t('Failed') %></span>
9
9
  </li>
10
10
  <li class="busy col-sm-1">
11
11
  <a href="<%= root_path %>busy">
12
- <span id="txtBusy" class="count"><%= number_with_delimiter(workset.size) %></span>
12
+ <span id="txtBusy" class="count" data-nwp><%= workset.size %></span>
13
13
  <span class="desc"><%= t('Busy') %></span>
14
14
  </a>
15
15
  </li>
16
16
  <li class="enqueued col-sm-1">
17
17
  <a href="<%= root_path %>queues">
18
- <span id="txtEnqueued" class="count"><%= number_with_delimiter(stats.enqueued) %></span>
18
+ <span id="txtEnqueued" class="count" data-nwp><%= stats.enqueued %></span>
19
19
  <span class="desc"><%= t('Enqueued') %></span>
20
20
  </a>
21
21
  </li>
22
22
  <li class="retries col-sm-1">
23
23
  <a href="<%= root_path %>retries">
24
- <span id="txtRetries" class="count"><%= number_with_delimiter(stats.retry_size) %></span>
24
+ <span id="txtRetries" class="count" data-nwp><%= stats.retry_size %></span>
25
25
  <span class="desc"><%= t('Retries') %></span>
26
26
  </a>
27
27
  </li>
28
28
  <li class="scheduled col-sm-1">
29
29
  <a href="<%= root_path %>scheduled">
30
- <span id="txtScheduled" class="count"><%= number_with_delimiter(stats.scheduled_size) %></span>
30
+ <span id="txtScheduled" class="count" data-nwp><%= stats.scheduled_size %></span>
31
31
  <span class="desc"><%= t('Scheduled') %></span>
32
32
  </a>
33
33
  </li>
34
34
  <li class="dead col-sm-1">
35
35
  <a href="<%= root_path %>morgue">
36
- <span id="txtDead" class="count"><%= number_with_delimiter(stats.dead_size) %></span>
36
+ <span id="txtDead" class="count" data-nwp><%= stats.dead_size %></span>
37
37
  <span class="desc"><%= t('Dead') %></span>
38
38
  </a>
39
39
  </li>
data/web/views/busy.erb CHANGED
@@ -86,9 +86,9 @@
86
86
  <% end %>
87
87
  </td>
88
88
  <td><%= relative_time(Time.at(process['started_at'])) %></td>
89
- <td><%= format_memory(process['rss'].to_i) %></td>
90
- <td><%= process['concurrency'] %></td>
91
- <td><%= process['busy'] %></td>
89
+ <td class="num"><%= format_memory(process['rss'].to_i) %></td>
90
+ <td class="num"><%= number_with_delimiter(process['concurrency']) %></td>
91
+ <td class="num"><%= number_with_delimiter(process['busy']) %></td>
92
92
  <td>
93
93
  <% unless process.embedded? %>
94
94
  <form method="POST">
@@ -125,14 +125,14 @@
125
125
  <th><%= t('Arguments') %></th>
126
126
  <th><%= t('Started') %></th>
127
127
  </thead>
128
- <% @workset.each do |process, thread, msg| %>
129
- <% job = Sidekiq::JobRecord.new(msg['payload']) %>
128
+ <% @workset.each do |process, thread, work| %>
129
+ <% job = work.job %>
130
130
  <tr>
131
131
  <td><%= process %></td>
132
132
  <td><%= thread %></td>
133
133
  <td><%= job.jid %></td>
134
134
  <td>
135
- <a href="<%= root_path %>queues/<%= msg['queue'] %>"><%= msg['queue'] %></a>
135
+ <a href="<%= root_path %>queues/<%= work.queue %>"><%= work.queue %></a>
136
136
  </td>
137
137
  <td>
138
138
  <%= job.display_class %>
@@ -141,7 +141,7 @@
141
141
  <td>
142
142
  <div class="args"><%= display_args(job.display_args) %></div>
143
143
  </td>
144
- <td><%= relative_time(Time.at(msg['run_at'])) %></td>
144
+ <td><%= relative_time(work.run_at) %></td>
145
145
  </tr>
146
146
  <% end %>
147
147
  </table>
@@ -1,7 +1,3 @@
1
- <script type="text/javascript" src="<%= root_path %>javascripts/chart.min.js"></script>
2
- <script type="text/javascript" src="<%= root_path %>javascripts/chartjs-plugin-annotation.min.js"></script>
3
- <script type="text/javascript" src="<%= root_path %>javascripts/base-charts.js"></script>
4
- <script type="text/javascript" src="<%= root_path %>javascripts/dashboard-charts.js"></script>
5
1
  <script type="text/javascript" src="<%= root_path %>javascripts/dashboard.js"></script>
6
2
  <div class= "dashboard clearfix">
7
3
  <h3 >
@@ -20,26 +16,19 @@
20
16
  </div>
21
17
 
22
18
  <div class="row chart">
23
- <canvas id="realtime-chart"></canvas>
24
- <script>
25
- window.realtimeChart = new RealtimeChart(
26
- document.getElementById("realtime-chart"),
27
- <%= Sidekiq.dump_json({
28
- processedLabel: t('Processed'),
29
- failedLabel: t('Failed'),
30
- labels: Array.new(50, ""),
31
- processed: Array.new(50),
32
- failed: Array.new(50),
33
- updateUrl: "#{root_path}stats",
34
- }) %>
35
- )
36
- </script>
19
+ <canvas id="realtime-chart">
20
+ <%= to_json({
21
+ processedLabel: t('Processed'),
22
+ failedLabel: t('Failed'),
23
+ labels: Array.new(50, ""),
24
+ processed: Array.new(50),
25
+ failed: Array.new(50),
26
+ updateUrl: "#{root_path}stats",
27
+ }) %>
28
+ </canvas>
37
29
 
38
30
  <!-- start with a space in the legend so the height doesn't change when we add content dynamically -->
39
31
  <div id="realtime-legend">&nbsp;</div>
40
- <script>
41
- realtimeChart.registerLegend(document.getElementById("realtime-legend"))
42
- </script>
43
32
  </div>
44
33
 
45
34
  <div class="row header">
@@ -55,18 +44,14 @@
55
44
  <a href="<%= root_path %>?days=180" class="history-graph <%= "active" if params[:days] == "180" %>"><%= t('SixMonths') %></a>
56
45
  </div>
57
46
 
58
- <canvas id="history-chart"></canvas>
59
- <script>
60
- window.historyChart = new DashboardChart(
61
- document.getElementById("history-chart"),
62
- <%= Sidekiq.dump_json({
63
- processedLabel: t('Processed'),
64
- failedLabel: t('Failed'),
65
- processed: @processed_history.to_a.reverse,
66
- failed: @failed_history.to_a.reverse,
67
- }) %>
68
- )
69
- </script>
47
+ <canvas id="history-chart">
48
+ <%= to_json({
49
+ processedLabel: t('Processed'),
50
+ failedLabel: t('Failed'),
51
+ processed: @processed_history.to_a.reverse,
52
+ failed: @failed_history.to_a.reverse,
53
+ }) %>
54
+ </canvas>
70
55
  </div>
71
56
 
72
57
  <br/>
@@ -113,3 +98,8 @@
113
98
  <% end %>
114
99
  </div>
115
100
  </div>
101
+
102
+ <script type="text/javascript" src="<%= root_path %>javascripts/chart.min.js"></script>
103
+ <script type="text/javascript" src="<%= root_path %>javascripts/chartjs-plugin-annotation.min.js"></script>
104
+ <script type="text/javascript" src="<%= root_path %>javascripts/base-charts.js"></script>
105
+ <script type="text/javascript" src="<%= root_path %>javascripts/dashboard-charts.js"></script>
@@ -1,7 +1,7 @@
1
- <div class="sm-col-3 pull-right" style="display: inline; margin: 25px 15px 0 0;">
2
- <%= t('Filter') %>:
3
- <form method="POST" action='<%= root_path %>filter/<%= which %>' style="display: inline-block">
1
+ <div>
2
+ <form method="post" class="form-inline" action='<%= root_path %>filter/<%= which %>'>
4
3
  <%= csrf_tag %>
5
- <input class="search" type="search" name="substr" value="<%= h params[:substr] %>" placeholder="<%= t('AnyJobContent') %>"/>
4
+ <label for="substr"><%= t('Filter') %></label>
5
+ <input class="search form-control" type="search" name="substr" value="<%= h params[:substr] %>" placeholder="<%= t('AnyJobContent') %>"/>
6
6
  </form>
7
7
  </div>
@@ -1,16 +1,29 @@
1
1
  <script type="text/javascript" src="<%= root_path %>javascripts/chart.min.js"></script>
2
2
  <script type="text/javascript" src="<%= root_path %>javascripts/chartjs-plugin-annotation.min.js"></script>
3
3
  <script type="text/javascript" src="<%= root_path %>javascripts/base-charts.js"></script>
4
- <script type="text/javascript" src="<%= root_path %>javascripts/metrics.js"></script>
5
4
 
6
5
  <div class="header-container">
7
6
  <div class="page-title-container">
8
7
  <h1><%= t('Metrics') %></h1>
9
-
10
8
  <a target="blank" href="https://github.com/sidekiq/sidekiq/wiki/Metrics"><span class="info-circle" title="Click to learn more about metrics">?</span></a>
11
9
  </div>
12
10
 
13
- <%= erb :_metrics_period_select, locals: { periods: @periods, period: @period, path: "#{root_path}metrics" } %>
11
+ <div>
12
+ <form id="metrics-form" class="form-inline" action="<%= root_path %>filter/metrics" method="post">
13
+ <%= csrf_tag %>
14
+ <label for="substr"><%= t('Filter') %></label>
15
+ <input id="class-filter" class="form-control" type="text" name="substr" placeholder="<%= t('Name') %>" value="<%= h params[:substr] %>">
16
+ <select id="period-selector" class="form-control" name="period">
17
+ <% @periods.each_key do |code| %>
18
+ <% if code == @period %>
19
+ <option selected value="<%= code %>"><%= code %></option>
20
+ <% else %>
21
+ <option value="<%= code %>"><%= code %></option>
22
+ <% end %>
23
+ <% end %>
24
+ </select>
25
+ </form>
26
+ </div>
14
27
  </div>
15
28
 
16
29
  <%
@@ -21,22 +34,17 @@
21
34
  %>
22
35
 
23
36
  <% if job_results.any? %>
24
- <canvas id="job-metrics-overview-chart"></canvas>
25
-
26
- <script>
27
- window.jobMetricsChart = new JobMetricsOverviewChart(
28
- document.getElementById("job-metrics-overview-chart"),
29
- <%= Sidekiq.dump_json({
30
- series: job_results.map { |(kls, jr)| [kls, jr.dig("series", "s")] }.to_h,
31
- marks: @query_result.marks.map { |m| [m.bucket, m.label] },
32
- labels: @query_result.buckets,
33
- visibleKls: visible_kls,
34
- yLabel: t('TotalExecutionTime'),
35
- units: t('Seconds').downcase,
36
- markLabel: t('Deploy'),
37
- }) %>
38
- )
39
- </script>
37
+ <canvas id="job-metrics-overview-chart">
38
+ <%= to_json({
39
+ series: job_results.map { |(kls, jr)| [kls, jr.dig("series", "s")] }.to_h,
40
+ marks: @query_result.marks.map { |m| [m.bucket, m.label] },
41
+ labels: @query_result.buckets,
42
+ visibleKls: visible_kls,
43
+ yLabel: t('TotalExecutionTime'),
44
+ units: t('Seconds').downcase,
45
+ markLabel: t('Deploy'),
46
+ }) %>
47
+ </canvas>
40
48
  <% end %>
41
49
 
42
50
  <div class="table_container">
@@ -46,8 +54,8 @@
46
54
  <th><%= t('Name') %></th>
47
55
  <th><%= t('Success') %></th>
48
56
  <th><%= t('Failure') %></th>
49
- <th><%= t('TotalExecutionTime') %></th>
50
- <th><%= t('AvgExecutionTime') %></th>
57
+ <th><%= t('TotalExecutionTime') %> (Seconds)</th>
58
+ <th><%= t('AvgExecutionTime') %> (Seconds)</th>
51
59
  </tr>
52
60
  <% if job_results.any? %>
53
61
  <% job_results.each_with_index do |(kls, jr), i| %>
@@ -64,12 +72,11 @@
64
72
  />
65
73
  <code><a href="<%= root_path %>metrics/<%= kls %>?period=<%= @period %>"><%= kls %></a></code>
66
74
  </div>
67
- <script>jobMetricsChart.registerSwatch("<%= id %>")</script>
68
75
  </td>
69
- <td><%= jr.dig("totals", "p") - jr.dig("totals", "f") %></td>
70
- <td><%= jr.dig("totals", "f") %></td>
71
- <td><%= jr.dig("totals", "s").round(2) %> seconds</td>
72
- <td><%= jr.total_avg("s").round(2) %> seconds</td>
76
+ <td class="num"><%= number_with_delimiter(jr.dig("totals", "p") - jr.dig("totals", "f")) %></td>
77
+ <td class="num"><%= number_with_delimiter(jr.dig("totals", "f")) %></td>
78
+ <td class="num"><%= number_with_delimiter(jr.dig("totals", "s"), precision: 2) %></td>
79
+ <td class="num"><%= number_with_delimiter(jr.total_avg("s"), precision: 2) %></td>
73
80
  </tr>
74
81
  <% end %>
75
82
  <% else %>
@@ -79,4 +86,6 @@
79
86
  </table>
80
87
  </div>
81
88
 
82
- <p><small>Data from <%= @query_result.starts_at %> to <%= @query_result.ends_at %></small></p>
89
+ <!--p><small>Data from <%= @query_result.starts_at %> to <%= @query_result.ends_at %></small></p-->
90
+
91
+ <script type="text/javascript" src="<%= root_path %>javascripts/metrics.js"></script>
@@ -1,7 +1,6 @@
1
1
  <script type="text/javascript" src="<%= root_path %>javascripts/chart.min.js"></script>
2
2
  <script type="text/javascript" src="<%= root_path %>javascripts/chartjs-plugin-annotation.min.js"></script>
3
3
  <script type="text/javascript" src="<%= root_path %>javascripts/base-charts.js"></script>
4
- <script type="text/javascript" src="<%= root_path %>javascripts/metrics.js"></script>
5
4
 
6
5
  <%
7
6
  job_result = @query_result.job_results[@name]
@@ -24,40 +23,30 @@
24
23
  <%= erb :_metrics_period_select, locals: { periods: @periods, period: @period, path: "#{root_path}metrics/#{@name}" } %>
25
24
  </div>
26
25
 
27
- <canvas id="hist-totals-chart"></canvas>
28
-
29
- <script>
30
- window.histTotalsChart = new HistTotalsChart(
31
- document.getElementById("hist-totals-chart"),
32
- <%= Sidekiq.dump_json({
33
- series: hist_totals,
34
- labels: bucket_labels,
35
- xLabel: t('ExecutionTime'),
36
- yLabel: t('Jobs'),
37
- units: t('Jobs').downcase,
38
- }) %>
39
- )
40
- </script>
41
-
42
- <canvas id="hist-bubble-chart"></canvas>
43
-
44
- <script>
45
- window.histBubbleChart = new HistBubbleChart(
46
- document.getElementById("hist-bubble-chart"),
47
- <%= Sidekiq.dump_json({
48
- hist: job_result.hist,
49
- marks: @query_result.marks.map { |m| [m.bucket, m.label] },
50
- labels: @query_result.buckets,
51
- histIntervals: bucket_intervals,
52
- yLabel: t('ExecutionTime'),
53
- markLabel: t('Deploy'),
54
- yUnits: t('Seconds').downcase,
55
- zUnits: t('Jobs').downcase,
56
- }) %>
57
- )
58
- </script>
59
-
60
- <p><small>Data from <%= @query_result.starts_at %> to <%= @query_result.ends_at %></small></p>
26
+ <canvas id="hist-totals-chart">
27
+ <%= to_json({
28
+ series: hist_totals,
29
+ labels: bucket_labels,
30
+ xLabel: t('ExecutionTime'),
31
+ yLabel: t('Jobs'),
32
+ units: t('Jobs').downcase,
33
+ }) %>
34
+ </canvas>
35
+
36
+ <canvas id="hist-bubble-chart">
37
+ <%= to_json({
38
+ hist: job_result.hist,
39
+ marks: @query_result.marks.map { |m| [m.bucket, m.label] },
40
+ labels: @query_result.buckets,
41
+ histIntervals: bucket_intervals,
42
+ yLabel: t('ExecutionTime'),
43
+ markLabel: t('Deploy'),
44
+ yUnits: t('Seconds').downcase,
45
+ zUnits: t('Jobs').downcase,
46
+ }) %>
47
+ </canvas>
48
+
49
+ <!--p><small>Data from <%= @query_result.starts_at %> to <%= @query_result.ends_at %></small></p-->
61
50
  <% else %>
62
51
  <h1>
63
52
  <a href="<%= root_path %>/metrics"><%= t('Metrics') %></a> /
@@ -66,3 +55,5 @@
66
55
 
67
56
  <div class="alert alert-success"><%= t('NoJobMetricsFound') %></div>
68
57
  <% end %>
58
+
59
+ <script type="text/javascript" src="<%= root_path %>javascripts/metrics.js"></script>
data/web/views/queues.erb CHANGED
@@ -18,8 +18,12 @@
18
18
  <span class="label label-danger"><%= t('Paused') %></span>
19
19
  <% end %>
20
20
  </td>
21
- <td><%= number_with_delimiter(queue.size) %> </td>
22
- <td><% queue_latency = queue.latency %><%= number_with_delimiter(queue_latency.round(2)) %><%= (queue_latency < 60) ? '' : " (#{relative_time(Time.at(Time.now.to_f - queue_latency))})" %> </td>
21
+ <td class="num"><%= number_with_delimiter(queue.size) %> </td>
22
+ <td class="num">
23
+ <% queue_latency = queue.latency %>
24
+ <%= (queue_latency < 60) ? '' : " (#{relative_time(Time.at(Time.now.to_f - queue_latency))})" %>
25
+ <%= number_with_delimiter(queue_latency, precision: 2) %>
26
+ </td>
23
27
  <td class="delete-confirm">
24
28
  <form action="<%=root_path %>queues/<%= CGI.escape(queue.name) %>" method="post">
25
29
  <%= csrf_tag %>
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.1.6
4
+ version: 7.2.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mike Perham
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-10-09 00:00:00.000000000 Z
11
+ date: 2024-04-26 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.14.0
19
+ version: 0.19.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.14.0
26
+ version: 0.19.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: connection_pool
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -78,6 +78,7 @@ files:
78
78
  - Changes.md
79
79
  - LICENSE.txt
80
80
  - README.md
81
+ - bin/multi_queue_bench
81
82
  - bin/sidekiq
82
83
  - bin/sidekiqload
83
84
  - bin/sidekiqmon