sidekiq 6.4.1 → 7.2.1

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.

Files changed (116) hide show
  1. checksums.yaml +4 -4
  2. data/Changes.md +307 -12
  3. data/README.md +43 -35
  4. data/bin/multi_queue_bench +268 -0
  5. data/bin/sidekiq +3 -8
  6. data/bin/sidekiqload +206 -114
  7. data/bin/sidekiqmon +3 -0
  8. data/lib/sidekiq/api.rb +356 -167
  9. data/lib/sidekiq/capsule.rb +127 -0
  10. data/lib/sidekiq/cli.rb +85 -89
  11. data/lib/sidekiq/client.rb +87 -59
  12. data/lib/sidekiq/component.rb +68 -0
  13. data/lib/sidekiq/config.rb +287 -0
  14. data/lib/sidekiq/deploy.rb +62 -0
  15. data/lib/sidekiq/embedded.rb +61 -0
  16. data/lib/sidekiq/fetch.rb +21 -22
  17. data/lib/sidekiq/job.rb +371 -10
  18. data/lib/sidekiq/job_logger.rb +2 -2
  19. data/lib/sidekiq/job_retry.rb +97 -58
  20. data/lib/sidekiq/job_util.rb +62 -20
  21. data/lib/sidekiq/launcher.rb +91 -83
  22. data/lib/sidekiq/logger.rb +6 -45
  23. data/lib/sidekiq/manager.rb +33 -32
  24. data/lib/sidekiq/metrics/query.rb +156 -0
  25. data/lib/sidekiq/metrics/shared.rb +95 -0
  26. data/lib/sidekiq/metrics/tracking.rb +140 -0
  27. data/lib/sidekiq/middleware/chain.rb +96 -51
  28. data/lib/sidekiq/middleware/current_attributes.rb +58 -20
  29. data/lib/sidekiq/middleware/i18n.rb +6 -4
  30. data/lib/sidekiq/middleware/modules.rb +21 -0
  31. data/lib/sidekiq/monitor.rb +17 -4
  32. data/lib/sidekiq/paginator.rb +11 -3
  33. data/lib/sidekiq/processor.rb +81 -80
  34. data/lib/sidekiq/rails.rb +21 -14
  35. data/lib/sidekiq/redis_client_adapter.rb +111 -0
  36. data/lib/sidekiq/redis_connection.rb +16 -85
  37. data/lib/sidekiq/ring_buffer.rb +29 -0
  38. data/lib/sidekiq/scheduled.rb +66 -38
  39. data/lib/sidekiq/testing/inline.rb +4 -4
  40. data/lib/sidekiq/testing.rb +67 -75
  41. data/lib/sidekiq/transaction_aware_client.rb +44 -0
  42. data/lib/sidekiq/version.rb +2 -1
  43. data/lib/sidekiq/web/action.rb +3 -3
  44. data/lib/sidekiq/web/application.rb +107 -10
  45. data/lib/sidekiq/web/csrf_protection.rb +8 -5
  46. data/lib/sidekiq/web/helpers.rb +65 -43
  47. data/lib/sidekiq/web.rb +19 -14
  48. data/lib/sidekiq/worker_compatibility_alias.rb +13 -0
  49. data/lib/sidekiq.rb +84 -207
  50. data/sidekiq.gemspec +12 -10
  51. data/web/assets/javascripts/application.js +92 -26
  52. data/web/assets/javascripts/base-charts.js +106 -0
  53. data/web/assets/javascripts/chart.min.js +13 -0
  54. data/web/assets/javascripts/chartjs-plugin-annotation.min.js +7 -0
  55. data/web/assets/javascripts/dashboard-charts.js +182 -0
  56. data/web/assets/javascripts/dashboard.js +10 -249
  57. data/web/assets/javascripts/metrics.js +298 -0
  58. data/web/assets/stylesheets/application-dark.css +4 -0
  59. data/web/assets/stylesheets/application-rtl.css +2 -91
  60. data/web/assets/stylesheets/application.css +75 -299
  61. data/web/locales/ar.yml +70 -70
  62. data/web/locales/cs.yml +62 -62
  63. data/web/locales/da.yml +60 -53
  64. data/web/locales/de.yml +65 -65
  65. data/web/locales/el.yml +43 -24
  66. data/web/locales/en.yml +84 -69
  67. data/web/locales/es.yml +68 -68
  68. data/web/locales/fa.yml +65 -65
  69. data/web/locales/fr.yml +81 -67
  70. data/web/locales/gd.yml +99 -0
  71. data/web/locales/he.yml +65 -64
  72. data/web/locales/hi.yml +59 -59
  73. data/web/locales/it.yml +53 -53
  74. data/web/locales/ja.yml +73 -68
  75. data/web/locales/ko.yml +52 -52
  76. data/web/locales/lt.yml +66 -66
  77. data/web/locales/nb.yml +61 -61
  78. data/web/locales/nl.yml +52 -52
  79. data/web/locales/pl.yml +45 -45
  80. data/web/locales/pt-br.yml +83 -55
  81. data/web/locales/pt.yml +51 -51
  82. data/web/locales/ru.yml +67 -66
  83. data/web/locales/sv.yml +53 -53
  84. data/web/locales/ta.yml +60 -60
  85. data/web/locales/uk.yml +62 -61
  86. data/web/locales/ur.yml +64 -64
  87. data/web/locales/vi.yml +67 -67
  88. data/web/locales/zh-cn.yml +43 -16
  89. data/web/locales/zh-tw.yml +42 -8
  90. data/web/views/_footer.erb +5 -2
  91. data/web/views/_job_info.erb +18 -2
  92. data/web/views/_metrics_period_select.erb +12 -0
  93. data/web/views/_nav.erb +1 -1
  94. data/web/views/_paging.erb +2 -0
  95. data/web/views/_poll_link.erb +1 -1
  96. data/web/views/_summary.erb +7 -7
  97. data/web/views/busy.erb +50 -34
  98. data/web/views/dashboard.erb +26 -4
  99. data/web/views/filtering.erb +7 -0
  100. data/web/views/metrics.erb +91 -0
  101. data/web/views/metrics_for_job.erb +59 -0
  102. data/web/views/morgue.erb +5 -9
  103. data/web/views/queue.erb +15 -15
  104. data/web/views/queues.erb +9 -3
  105. data/web/views/retries.erb +5 -9
  106. data/web/views/scheduled.erb +12 -13
  107. metadata +58 -27
  108. data/lib/sidekiq/delay.rb +0 -43
  109. data/lib/sidekiq/exception_handler.rb +0 -27
  110. data/lib/sidekiq/extensions/action_mailer.rb +0 -48
  111. data/lib/sidekiq/extensions/active_record.rb +0 -43
  112. data/lib/sidekiq/extensions/class_methods.rb +0 -43
  113. data/lib/sidekiq/extensions/generic_proxy.rb +0 -33
  114. data/lib/sidekiq/util.rb +0 -108
  115. data/lib/sidekiq/worker.rb +0 -362
  116. /data/{LICENSE → LICENSE.txt} +0 -0
data/web/views/busy.erb CHANGED
@@ -1,7 +1,5 @@
1
- <div class="row header">
2
- <div class="col-sm-4 pull-left flip">
3
- <h3><%= t('Status') %></h3>
4
- </div>
1
+ <div class="header-container">
2
+ <h1><%= t('Status') %></h1>
5
3
  </div>
6
4
 
7
5
  <div class="stats-wrapper">
@@ -15,7 +13,7 @@
15
13
  <p><%= t('Threads') %></p>
16
14
  </div>
17
15
  <div class="stat">
18
- <h3><%= ws = workers.size; number_with_delimiter(ws) %></h3>
16
+ <h3><%= ws = workset.size; number_with_delimiter(ws) %></h3>
19
17
  <p><%= t('Busy') %></p>
20
18
  </div>
21
19
  <div class="stat">
@@ -29,32 +27,31 @@
29
27
  </div>
30
28
  </div>
31
29
 
32
- <div class="row header">
33
- <div class="col-sm-4 pull-left flip">
34
- <h3><%= t('Processes') %></h3>
35
- </div>
36
- <div class="col-sm-3 pull-right flip">
30
+ <div class="header-container">
31
+ <h1><%= t('Processes') %></h1>
32
+ <div>
37
33
  <form method="POST" class="warning-messages">
38
34
  <%= csrf_tag %>
39
35
  <div class="btn-group pull-right flip">
40
- <button class="btn btn-warn" type="submit" name="quiet" value="1" data-confirm="<%= t('AreYouSure') %>"><%= t('QuietAll') %></button>
41
- <button class="btn btn-danger" type="submit" name="stop" value="1" data-confirm="<%= t('AreYouSure') %>"><%= t('StopAll') %></button>
36
+ <input class="btn btn-warn" type="submit" name="quiet" value="<%= t('QuietAll') %>" data-confirm="<%= t('AreYouSure') %>"/>
37
+ <input class="btn btn-danger" type="submit" name="stop" value="<%= t('StopAll') %>" data-confirm="<%= t('AreYouSure') %>"/>
42
38
  </div>
43
39
  </form>
44
40
  </div>
45
41
  </div>
42
+
46
43
  <div class="table_container">
47
44
  <table class="processes table table-hover table-bordered table-striped">
48
45
  <thead>
49
46
  <th><%= t('Name') %></th>
50
47
  <th><%= t('Started') %></th>
51
- <th class="col-sm-1"><%= t('RSS') %><a href="https://github.com/mperham/sidekiq/wiki/Memory#rss"><span class="info-circle" title="Click to learn more about RSS">?</span></a></th>
48
+ <th class="col-sm-1"><%= t('RSS') %><a target="blank" href="https://github.com/sidekiq/sidekiq/wiki/Memory#rss"><span class="info-circle" title="Click to learn more about RSS">?</span></a></th>
52
49
  <th class="col-sm-1"><%= t('Threads') %></th>
53
50
  <th class="col-sm-1"><%= t('Busy') %></th>
54
51
  <th>&nbsp;</th>
55
52
  </thead>
56
53
  <% lead = processes.leader %>
57
- <% processes.each do |process| %>
54
+ <% sorted_processes.each do |process| %>
58
55
  <tr>
59
56
  <td class="box">
60
57
  <%= "#{process['hostname']}:#{process['pid']}" %>
@@ -62,6 +59,9 @@
62
59
  <% process.labels.each do |label| %>
63
60
  <span class="label label-info"><%= label %></span>
64
61
  <% end %>
62
+ <% if process.embedded? %>
63
+ <span class="label label-default">embedded</span>
64
+ <% end %>
65
65
  <% if process.stopping? %>
66
66
  <span class="label label-danger">quiet</span>
67
67
  <% end %>
@@ -70,32 +70,48 @@
70
70
  <% end %>
71
71
  <br>
72
72
  <b><%= "#{t('Queues')}: " %></b>
73
- <%= process.queues.join(", ") %>
73
+ <% if process.weights %>
74
+ <%= busy_weights(process.weights) %>
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
- <td><%= format_memory(process['rss'].to_i) %></td>
77
- <td><%= process['concurrency'] %></td>
78
- <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>
79
92
  <td>
80
- <form method="POST">
81
- <%= csrf_tag %>
82
- <input type="hidden" name="identity" value="<%= process['identity'] %>"/>
93
+ <% unless process.embedded? %>
94
+ <form method="POST">
95
+ <%= csrf_tag %>
96
+ <input type="hidden" name="identity" value="<%= process['identity'] %>"/>
83
97
 
84
- <div class="btn-group pull-right flip">
85
- <% unless process.stopping? %><button class="btn btn-xs btn-warn" type="submit" name="quiet" value="1"><%= t('Quiet') %></button><% end %>
86
- <button class="btn btn-xs btn-danger" type="submit" name="stop" value="1"><%= t('Stop') %></button>
87
- </div>
88
- </form>
98
+ <div class="btn-group pull-right flip">
99
+ <% unless process.stopping? %><button class="btn btn-xs btn-warn" type="submit" name="quiet" value="1"><%= t('Quiet') %></button><% end %>
100
+ <button class="btn btn-xs btn-danger" type="submit" name="stop" value="1"><%= t('Stop') %></button>
101
+ </div>
102
+ </form>
103
+ <% end %>
89
104
  </td>
90
105
  </tr>
91
106
  <% end %>
92
107
  </table>
93
108
  </div>
94
109
 
95
- <div class="row header">
96
- <div class="col-sm-7">
97
- <h3><%= t('Jobs') %></h3>
98
- </div>
110
+ <div class="header-container">
111
+ <h1><%= t('Jobs') %></h1>
112
+ <% if @workset.size > 0 && @total_size > @count %>
113
+ <%= erb :_paging, locals: { url: "#{root_path}busy" } %>
114
+ <% end %>
99
115
  </div>
100
116
 
101
117
  <div class="table_container">
@@ -109,14 +125,14 @@
109
125
  <th><%= t('Arguments') %></th>
110
126
  <th><%= t('Started') %></th>
111
127
  </thead>
112
- <% workers.each do |process, thread, msg| %>
113
- <% job = Sidekiq::JobRecord.new(msg['payload']) %>
128
+ <% @workset.each do |process, thread, work| %>
129
+ <% job = work.job %>
114
130
  <tr>
115
131
  <td><%= process %></td>
116
132
  <td><%= thread %></td>
117
133
  <td><%= job.jid %></td>
118
134
  <td>
119
- <a href="<%= root_path %>queues/<%= msg['queue'] %>"><%= msg['queue'] %></a>
135
+ <a href="<%= root_path %>queues/<%= work.queue %>"><%= work.queue %></a>
120
136
  </td>
121
137
  <td>
122
138
  <%= job.display_class %>
@@ -125,7 +141,7 @@
125
141
  <td>
126
142
  <div class="args"><%= display_args(job.display_args) %></div>
127
143
  </td>
128
- <td><%= relative_time(Time.at(msg['run_at'])) %></td>
144
+ <td><%= relative_time(work.run_at) %></td>
129
145
  </tr>
130
146
  <% end %>
131
147
  </table>
@@ -16,8 +16,19 @@
16
16
  </div>
17
17
 
18
18
  <div class="row chart">
19
- <div id="realtime" data-processed-label="<%= t('Processed') %>" data-failed-label="<%= t('Failed') %>"></div>
20
- <div id="realtime-legend"></div>
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>
29
+
30
+ <!-- start with a space in the legend so the height doesn't change when we add content dynamically -->
31
+ <div id="realtime-legend">&nbsp;</div>
21
32
  </div>
22
33
 
23
34
  <div class="row header">
@@ -33,8 +44,14 @@
33
44
  <a href="<%= root_path %>?days=180" class="history-graph <%= "active" if params[:days] == "180" %>"><%= t('SixMonths') %></a>
34
45
  </div>
35
46
 
36
- <div id="history" data-processed-label="<%= t('Processed') %>" data-failed-label="<%= t('Failed') %>" data-processed="<%= h Sidekiq.dump_json(@processed_history) %>" data-failed="<%= h Sidekiq.dump_json(@failed_history) %>" data-update-url="<%= root_path %>stats"></div>
37
- <div id="history-legend"></div>
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>
38
55
  </div>
39
56
 
40
57
  <br/>
@@ -81,3 +98,8 @@
81
98
  <% end %>
82
99
  </div>
83
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>
@@ -0,0 +1,7 @@
1
+ <div>
2
+ <form method="post" class="form-inline" action='<%= root_path %>filter/<%= which %>'>
3
+ <%= csrf_tag %>
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
+ </form>
7
+ </div>
@@ -0,0 +1,91 @@
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
+
5
+ <div class="header-container">
6
+ <div class="page-title-container">
7
+ <h1><%= t('Metrics') %></h1>
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>
9
+ </div>
10
+
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="<%= 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>
27
+ </div>
28
+
29
+ <%
30
+ table_limit = 20
31
+ chart_limit = 5
32
+ job_results = @query_result.job_results.sort_by { |(kls, jr)| jr.totals["s"] }.reverse.first(table_limit)
33
+ visible_kls = job_results.first(chart_limit).map(&:first)
34
+ %>
35
+
36
+ <% if job_results.any? %>
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>
48
+ <% end %>
49
+
50
+ <div class="table_container">
51
+ <table class="table table-bordered table-striped table-hover">
52
+ <tbody>
53
+ <tr>
54
+ <th><%= t('Name') %></th>
55
+ <th><%= t('Success') %></th>
56
+ <th><%= t('Failure') %></th>
57
+ <th><%= t('TotalExecutionTime') %> (Seconds)</th>
58
+ <th><%= t('AvgExecutionTime') %> (Seconds)</th>
59
+ </tr>
60
+ <% if job_results.any? %>
61
+ <% job_results.each_with_index do |(kls, jr), i| %>
62
+ <tr>
63
+ <td>
64
+ <div class="metrics-swatch-wrapper">
65
+ <% id = "metrics-swatch-#{kls}" %>
66
+ <input
67
+ type="checkbox"
68
+ id="<%= id %>"
69
+ class="metrics-swatch"
70
+ value="<%= kls %>"
71
+ <%= visible_kls.include?(kls) ? 'checked' : '' %>
72
+ />
73
+ <code><a href="<%= root_path %>metrics/<%= kls %>?period=<%= @period %>"><%= kls %></a></code>
74
+ </div>
75
+ </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>
80
+ </tr>
81
+ <% end %>
82
+ <% else %>
83
+ <tr><td colspan=5><%= t("NoDataFound") %></td></tr>
84
+ <% end %>
85
+ </tbody>
86
+ </table>
87
+ </div>
88
+
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>
@@ -0,0 +1,59 @@
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
+
5
+ <%
6
+ job_result = @query_result.job_results[@name]
7
+ hist_totals = job_result.hist.values.first.zip(*job_result.hist.values[1..-1]).map(&:sum).reverse
8
+ bucket_labels = Sidekiq::Metrics::Histogram::LABELS
9
+ bucket_intervals = Sidekiq::Metrics::Histogram::BUCKET_INTERVALS
10
+ %>
11
+
12
+ <% if job_result.totals["s"] > 0 %>
13
+ <div class="header-container">
14
+ <div class="page-title-container">
15
+ <h1>
16
+ <a href="<%= root_path %>metrics?period=<%= @period %>"><%= t('Metrics') %></a> /
17
+ <%= h @name %>
18
+ </h1>
19
+
20
+ <a target="blank" href="https://github.com/sidekiq/sidekiq/wiki/Metrics"><span class="info-circle" title="Click to learn more about metrics">?</span></a>
21
+ </div>
22
+
23
+ <%= erb :_metrics_period_select, locals: { periods: @periods, period: @period, path: "#{root_path}metrics/#{@name}" } %>
24
+ </div>
25
+
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-->
50
+ <% else %>
51
+ <h1>
52
+ <a href="<%= root_path %>/metrics"><%= t('Metrics') %></a> /
53
+ <%= h @name %>
54
+ </h1>
55
+
56
+ <div class="alert alert-success"><%= t('NoJobMetricsFound') %></div>
57
+ <% end %>
58
+
59
+ <script type="text/javascript" src="<%= root_path %>javascripts/metrics.js"></script>
data/web/views/morgue.erb CHANGED
@@ -1,14 +1,10 @@
1
- <header class="row">
2
- <div class="col-sm-5">
3
- <h3><%= t('DeadJobs') %></h3>
4
- </div>
1
+ <div class="header-container">
2
+ <h1><%= t('DeadJobs') %></h1>
5
3
  <% if @dead.size > 0 && @total_size > @count %>
6
- <div class="col-sm-4">
7
- <%= erb :_paging, locals: { url: "#{root_path}morgue" } %>
8
- </div>
4
+ <%= erb :_paging, locals: { url: "#{root_path}morgue" } %>
9
5
  <% end %>
10
6
  <%= filtering('dead') %>
11
- </header>
7
+ </div>
12
8
 
13
9
  <% if @dead.size > 0 %>
14
10
  <form action="<%= root_path %>morgue" method="post">
@@ -33,7 +29,7 @@
33
29
  <tr>
34
30
  <td class="table-checkbox">
35
31
  <label>
36
- <input type='checkbox' name='key[]' value='<%= job_params(entry.item, entry.score) %>' />
32
+ <input type='checkbox' name='key[]' value='<%= job_params(entry.item, entry.score) %>' class='shift_clickable' />
37
33
  </label>
38
34
  </td>
39
35
  <td>
data/web/views/queue.erb CHANGED
@@ -1,23 +1,20 @@
1
- <header class="row">
2
- <div class="col-sm-5">
3
- <h3>
4
- <%= t('CurrentMessagesInQueue', :queue => h(@name)) %>
5
- <% if @queue.paused? %>
6
- <span class="label label-danger"><%= t('Paused') %></span>
7
- <% end %>
8
- <span class="badge badge-secondary"><%= number_with_delimiter(@total_size) %></span>
9
- </h3>
10
- </div>
11
- <div class="col-sm-4 pull-right flip">
12
- <%= erb :_paging, locals: { url: "#{root_path}queues/#{CGI.escape(@name)}" } %>
13
- </div>
14
- </header>
1
+ <div class="header-container">
2
+ <h1><%= t('CurrentMessagesInQueue', :queue => h(@name)) %>
3
+ <% if @queue.paused? %>
4
+ <span class="label label-danger"><%= t('Paused') %></span>
5
+ <% end %>
6
+ <span class="badge badge-secondary"><%= number_with_delimiter(@total_size) %></span>
7
+ </h1>
8
+ <%= erb :_paging, locals: { url: "#{root_path}queues/#{CGI.escape(@name)}" } %>
9
+ </div>
10
+
15
11
  <div class="table_container">
16
12
  <table class="queue table table-hover table-bordered table-striped">
17
13
  <thead>
18
14
  <th><a href="<%= url %>?direction=<%= params[:direction] == 'asc' ? 'desc' : 'asc' %>"># <%= sort_direction_label %></a></th>
19
15
  <th><%= t('Job') %></th>
20
16
  <th><%= t('Arguments') %></th>
17
+ <th><%= t('Context') %></th>
21
18
  <th></th>
22
19
  </thead>
23
20
  <% @jobs.each_with_index do |job, index| %>
@@ -35,12 +32,15 @@
35
32
  <% a = job.display_args %>
36
33
  <% if a.inspect.size > 100 %>
37
34
  <span id="job_<%= index %>"><%= h(a.inspect[0..100]) + "... " %></span>
38
- <button data-toggle="job_<%= index %>" class="btn btn-default btn-xs"><%= t('ShowAll') %></button>
35
+ <button data-toggle="job_<%= index %>_full" class="btn btn-default btn-xs"><%= t('ShowAll') %></button>
39
36
  <div class="toggle" id="job_<%= index %>_full"><%= display_args(a) %></div>
40
37
  <% else %>
41
38
  <%= display_args(job.display_args) %>
42
39
  <% end %>
43
40
  </td>
41
+ <td>
42
+ <%= h(job["cattr"].inspect) if job["cattr"]&.any? %>
43
+ </td>
44
44
  <td>
45
45
  <form action="<%= root_path %>queues/<%= CGI.escape(@name) %>/delete" method="post">
46
46
  <%= csrf_tag %>
data/web/views/queues.erb CHANGED
@@ -1,4 +1,6 @@
1
- <h3><%= t('Queues') %></h3>
1
+ <div class="header-container">
2
+ <h1><%= t('Queues') %></h1>
3
+ </div>
2
4
 
3
5
  <div class="table_container">
4
6
  <table class="queues table table-hover table-bordered table-striped">
@@ -16,8 +18,12 @@
16
18
  <span class="label label-danger"><%= t('Paused') %></span>
17
19
  <% end %>
18
20
  </td>
19
- <td><%= number_with_delimiter(queue.size) %> </td>
20
- <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>
21
27
  <td class="delete-confirm">
22
28
  <form action="<%=root_path %>queues/<%= CGI.escape(queue.name) %>" method="post">
23
29
  <%= csrf_tag %>
@@ -1,14 +1,10 @@
1
- <header class="row">
2
- <div class="col-sm-5">
3
- <h3><%= t('Retries') %></h3>
4
- </div>
1
+ <div class="header-container">
2
+ <h1><%= t('Retries') %></h1>
5
3
  <% if @retries.size > 0 && @total_size > @count %>
6
- <div class="col-sm-4">
7
- <%= erb :_paging, locals: { url: "#{root_path}retries" } %>
8
- </div>
4
+ <%= erb :_paging, locals: { url: "#{root_path}retries" } %>
9
5
  <% end %>
10
6
  <%= filtering('retries') %>
11
- </header>
7
+ </div>
12
8
 
13
9
  <% if @retries.size > 0 %>
14
10
  <form action="<%= root_path %>retries" method="post">
@@ -34,7 +30,7 @@
34
30
  <tr>
35
31
  <td class="table-checkbox">
36
32
  <label>
37
- <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' />
38
34
  </label>
39
35
  </td>
40
36
  <td>
@@ -1,25 +1,22 @@
1
- <header class="row">
2
- <div class="col-sm-5">
3
- <h3><%= t('ScheduledJobs') %></h3>
4
- </div>
1
+ <div class="header-container">
2
+ <h1><%= t('ScheduledJobs') %></h1>
5
3
  <% if @scheduled.size > 0 && @total_size > @count %>
6
- <div class="col-sm-4">
7
- <%= erb :_paging, locals: { url: "#{root_path}scheduled" } %>
8
- </div>
4
+ <%= erb :_paging, locals: { url: "#{root_path}scheduled" } %>
9
5
  <% end %>
10
6
  <%= filtering('scheduled') %>
11
- </header>
7
+ </div>
12
8
 
13
9
  <% if @scheduled.size > 0 %>
14
-
15
10
  <form action="<%= root_path %>scheduled" method="post">
16
11
  <%= csrf_tag %>
17
12
  <div class="table_container">
18
13
  <table class="table table-striped table-bordered table-hover">
19
14
  <thead>
20
15
  <tr>
21
- <th class="checkbox-column">
22
- <input type="checkbox" class="check_all" />
16
+ <th class="table-checkbox checkbox-column">
17
+ <label>
18
+ <input type="checkbox" class="check_all" />
19
+ </label>
23
20
  </th>
24
21
  <th><%= t('When') %></th>
25
22
  <th><%= t('Queue') %></th>
@@ -29,8 +26,10 @@
29
26
  </thead>
30
27
  <% @scheduled.each do |entry| %>
31
28
  <tr>
32
- <td>
33
- <input type='checkbox' name='key[]' value='<%= job_params(entry.item, entry.score) %>' />
29
+ <td class="table-checkbox">
30
+ <label>
31
+ <input type='checkbox' name='key[]' value='<%= job_params(entry.item, entry.score) %>' class='shift_clickable' />
32
+ </label>
34
33
  </td>
35
34
  <td>
36
35
  <a href="<%= root_path %>scheduled/<%= job_params(entry.item, entry.score) %>"><%= relative_time(entry.at) %></a>