sidekiq 5.2.9 → 6.1.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.

Files changed (89) hide show
  1. checksums.yaml +4 -4
  2. data/.github/ISSUE_TEMPLATE/bug_report.md +20 -0
  3. data/.github/workflows/ci.yml +41 -0
  4. data/.gitignore +0 -2
  5. data/.standard.yml +20 -0
  6. data/6.0-Upgrade.md +72 -0
  7. data/Changes.md +184 -0
  8. data/Ent-2.0-Upgrade.md +37 -0
  9. data/Ent-Changes.md +44 -1
  10. data/Gemfile +12 -11
  11. data/Gemfile.lock +192 -0
  12. data/Pro-5.0-Upgrade.md +25 -0
  13. data/Pro-Changes.md +48 -2
  14. data/README.md +18 -34
  15. data/Rakefile +5 -4
  16. data/bin/sidekiq +26 -2
  17. data/bin/sidekiqload +32 -24
  18. data/bin/sidekiqmon +8 -0
  19. data/lib/generators/sidekiq/templates/worker_test.rb.erb +1 -1
  20. data/lib/generators/sidekiq/worker_generator.rb +21 -13
  21. data/lib/sidekiq/api.rb +242 -219
  22. data/lib/sidekiq/cli.rb +131 -180
  23. data/lib/sidekiq/client.rb +67 -47
  24. data/lib/sidekiq/delay.rb +5 -6
  25. data/lib/sidekiq/exception_handler.rb +10 -12
  26. data/lib/sidekiq/extensions/action_mailer.rb +13 -22
  27. data/lib/sidekiq/extensions/active_record.rb +13 -10
  28. data/lib/sidekiq/extensions/class_methods.rb +14 -11
  29. data/lib/sidekiq/extensions/generic_proxy.rb +4 -4
  30. data/lib/sidekiq/fetch.rb +29 -30
  31. data/lib/sidekiq/job_logger.rb +45 -7
  32. data/lib/sidekiq/job_retry.rb +61 -61
  33. data/lib/sidekiq/launcher.rb +88 -55
  34. data/lib/sidekiq/logger.rb +165 -0
  35. data/lib/sidekiq/manager.rb +11 -13
  36. data/lib/sidekiq/middleware/chain.rb +15 -5
  37. data/lib/sidekiq/middleware/i18n.rb +5 -7
  38. data/lib/sidekiq/monitor.rb +133 -0
  39. data/lib/sidekiq/paginator.rb +18 -14
  40. data/lib/sidekiq/processor.rb +71 -70
  41. data/lib/sidekiq/rails.rb +29 -37
  42. data/lib/sidekiq/redis_connection.rb +50 -48
  43. data/lib/sidekiq/scheduled.rb +28 -29
  44. data/lib/sidekiq/sd_notify.rb +149 -0
  45. data/lib/sidekiq/systemd.rb +24 -0
  46. data/lib/sidekiq/testing/inline.rb +2 -1
  47. data/lib/sidekiq/testing.rb +35 -24
  48. data/lib/sidekiq/util.rb +17 -16
  49. data/lib/sidekiq/version.rb +2 -1
  50. data/lib/sidekiq/web/action.rb +14 -10
  51. data/lib/sidekiq/web/application.rb +73 -71
  52. data/lib/sidekiq/web/csrf_protection.rb +158 -0
  53. data/lib/sidekiq/web/helpers.rb +85 -77
  54. data/lib/sidekiq/web/router.rb +18 -17
  55. data/lib/sidekiq/web.rb +53 -53
  56. data/lib/sidekiq/worker.rb +126 -102
  57. data/lib/sidekiq.rb +69 -44
  58. data/sidekiq.gemspec +15 -16
  59. data/web/assets/javascripts/application.js +25 -27
  60. data/web/assets/javascripts/dashboard.js +4 -23
  61. data/web/assets/stylesheets/application-dark.css +143 -0
  62. data/web/assets/stylesheets/application.css +16 -6
  63. data/web/locales/de.yml +14 -2
  64. data/web/locales/en.yml +2 -0
  65. data/web/locales/fr.yml +2 -2
  66. data/web/locales/ja.yml +4 -1
  67. data/web/locales/lt.yml +83 -0
  68. data/web/locales/pl.yml +4 -4
  69. data/web/locales/ru.yml +4 -0
  70. data/web/locales/vi.yml +83 -0
  71. data/web/views/_job_info.erb +2 -1
  72. data/web/views/busy.erb +6 -3
  73. data/web/views/dead.erb +2 -2
  74. data/web/views/layout.erb +1 -0
  75. data/web/views/morgue.erb +5 -2
  76. data/web/views/queue.erb +10 -1
  77. data/web/views/queues.erb +9 -1
  78. data/web/views/retries.erb +5 -2
  79. data/web/views/retry.erb +2 -2
  80. data/web/views/scheduled.erb +5 -2
  81. metadata +25 -43
  82. data/.circleci/config.yml +0 -61
  83. data/.github/issue_template.md +0 -11
  84. data/.travis.yml +0 -11
  85. data/bin/sidekiqctl +0 -20
  86. data/lib/sidekiq/core_ext.rb +0 -1
  87. data/lib/sidekiq/ctl.rb +0 -221
  88. data/lib/sidekiq/logging.rb +0 -122
  89. data/lib/sidekiq/middleware/server/active_record.rb +0 -23
data/web/views/dead.erb CHANGED
@@ -14,11 +14,11 @@
14
14
  <th><%= t('ErrorMessage') %></th>
15
15
  <td><%= h(@dead['error_message']) %></td>
16
16
  </tr>
17
- <% if !@dead['error_backtrace'].nil? %>
17
+ <% if @dead.error_backtrace %>
18
18
  <tr>
19
19
  <th><%= t('ErrorBacktrace') %></th>
20
20
  <td>
21
- <code><%= @dead['error_backtrace'].join("<br/>") %></code>
21
+ <code><%= @dead.error_backtrace.join("<br/>") %></code>
22
22
  </td>
23
23
  </tr>
24
24
  <% end %>
data/web/views/layout.erb CHANGED
@@ -11,6 +11,7 @@
11
11
  <% end %>
12
12
 
13
13
  <link href="<%= root_path %>stylesheets/application.css" media="screen" rel="stylesheet" type="text/css" />
14
+ <link href="<%= root_path %>stylesheets/application-dark.css" media="screen and (prefers-color-scheme: dark)" rel="stylesheet" type="text/css" />
14
15
  <% if rtl? %>
15
16
  <link href="<%= root_path %>stylesheets/application-rtl.css" media="screen" rel="stylesheet" type="text/css" />
16
17
  <% end %>
data/web/views/morgue.erb CHANGED
@@ -14,7 +14,7 @@
14
14
  <form action="<%= root_path %>morgue" method="post">
15
15
  <%= csrf_tag %>
16
16
  <div class="table_container">
17
- <table class="table table-striped table-bordered table-white">
17
+ <table class="table table-striped table-bordered">
18
18
  <thead>
19
19
  <tr>
20
20
  <th class="table-checkbox checkbox-column">
@@ -42,7 +42,10 @@
42
42
  <td>
43
43
  <a href="<%= root_path %>queues/<%= entry.queue %>"><%= entry.queue %></a>
44
44
  </td>
45
- <td><%= entry.display_class %></td>
45
+ <td>
46
+ <%= entry.display_class %>
47
+ <%= display_tags(entry, "morgue") %>
48
+ </td>
46
49
  <td>
47
50
  <div class="args"><%= display_args(entry.display_args) %></div>
48
51
  </td>
data/web/views/queue.erb CHANGED
@@ -15,13 +15,22 @@
15
15
  <div class="table_container">
16
16
  <table class="queue table table-hover table-bordered table-striped">
17
17
  <thead>
18
+ <th><a href="<%= url %>?direction=<%= params[:direction] == 'asc' ? 'desc' : 'asc' %>"># <%= sort_direction_label %></a></th>
18
19
  <th><%= t('Job') %></th>
19
20
  <th><%= t('Arguments') %></th>
20
21
  <th></th>
21
22
  </thead>
22
23
  <% @messages.each_with_index do |msg, index| %>
23
24
  <tr>
24
- <td><%= h(msg.display_class) %></td>
25
+ <% if params[:direction] == 'asc' %>
26
+ <td><%= @count * (@current_page - 1) + index + 1 %></td>
27
+ <% else %>
28
+ <td><%= @total_size - (@count * (@current_page - 1) + index) %></td>
29
+ <% end %>
30
+ <td>
31
+ <%= h(msg.display_class) %>
32
+ <%= display_tags(msg, nil) %>
33
+ </td>
25
34
  <td>
26
35
  <% a = msg.display_args %>
27
36
  <% if a.inspect.size > 100 %>
data/web/views/queues.erb CHANGED
@@ -1,7 +1,7 @@
1
1
  <h3><%= t('Queues') %></h3>
2
2
 
3
3
  <div class="table_container">
4
- <table class="queues table table-hover table-bordered table-striped table-white">
4
+ <table class="queues table table-hover table-bordered table-striped">
5
5
  <thead>
6
6
  <th><%= t('Queue') %></th>
7
7
  <th><%= t('Size') %></th>
@@ -22,6 +22,14 @@
22
22
  <form action="<%=root_path %>queues/<%= CGI.escape(queue.name) %>" method="post">
23
23
  <%= csrf_tag %>
24
24
  <input class="btn btn-danger btn-xs" type="submit" name="delete" value="<%= t('Delete') %>" data-confirm="<%= t('AreYouSureDeleteQueue', :queue => h(queue.name)) %>" />
25
+
26
+ <% if Sidekiq.pro? %>
27
+ <% if queue.paused? %>
28
+ <input class="btn btn-danger btn-xs" type="submit" name="unpause" value="<%= t('Unpause') %>" />
29
+ <% else %>
30
+ <input class="btn btn-danger btn-xs" type="submit" name="pause" value="<%= t('Pause') %>" />
31
+ <% end %>
32
+ <% end %>
25
33
  </form>
26
34
  </td>
27
35
  </tr>
@@ -14,7 +14,7 @@
14
14
  <form action="<%= root_path %>retries" method="post">
15
15
  <%= csrf_tag %>
16
16
  <div class="table_container">
17
- <table class="table table-striped table-bordered table-white">
17
+ <table class="table table-striped table-bordered">
18
18
  <thead>
19
19
  <tr>
20
20
  <th class="table-checkbox checkbox-column">
@@ -44,7 +44,10 @@
44
44
  <td>
45
45
  <a href="<%= root_path %>queues/<%= entry.queue %>"><%= entry.queue %></a>
46
46
  </td>
47
- <td><%= entry.display_class %></td>
47
+ <td>
48
+ <%= entry.display_class %>
49
+ <%= display_tags(entry, "retries") %>
50
+ </td>
48
51
  <td>
49
52
  <div class="args"><%= display_args(entry.display_args) %></div>
50
53
  </td>
data/web/views/retry.erb CHANGED
@@ -14,11 +14,11 @@
14
14
  <th><%= t('ErrorMessage') %></th>
15
15
  <td><%= h(@retry['error_message']) %></td>
16
16
  </tr>
17
- <% if !@retry['error_backtrace'].nil? %>
17
+ <% if @retry.error_backtrace %>
18
18
  <tr>
19
19
  <th><%= t('ErrorBacktrace') %></th>
20
20
  <td>
21
- <code><%= @retry['error_backtrace'].join("<br/>") %></code>
21
+ <code><%= @retry.error_backtrace.join("<br/>") %></code>
22
22
  </td>
23
23
  </tr>
24
24
  <% end %>
@@ -15,7 +15,7 @@
15
15
  <form action="<%= root_path %>scheduled" method="post">
16
16
  <%= csrf_tag %>
17
17
  <div class="table_container">
18
- <table class="table table-striped table-bordered table-white">
18
+ <table class="table table-striped table-bordered">
19
19
  <thead>
20
20
  <tr>
21
21
  <th class="checkbox-column">
@@ -38,7 +38,10 @@
38
38
  <td>
39
39
  <a href="<%= root_path %>queues/<%= entry.queue %>"><%= entry.queue %></a>
40
40
  </td>
41
- <td><%= entry.display_class %></td>
41
+ <td>
42
+ <%= entry.display_class %>
43
+ <%= display_tags(entry, "scheduled") %>
44
+ </td>
42
45
  <td>
43
46
  <div class="args"><%= display_args(entry.display_args) %></div>
44
47
  </td>
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: 5.2.9
4
+ version: 6.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mike Perham
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-06-16 00:00:00.000000000 Z
11
+ date: 2020-09-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: redis
@@ -16,27 +16,18 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: 3.3.5
20
- - - "<"
21
- - !ruby/object:Gem::Version
22
- version: '4.2'
19
+ version: 4.2.0
23
20
  type: :runtime
24
21
  prerelease: false
25
22
  version_requirements: !ruby/object:Gem::Requirement
26
23
  requirements:
27
24
  - - ">="
28
25
  - !ruby/object:Gem::Version
29
- version: 3.3.5
30
- - - "<"
31
- - !ruby/object:Gem::Version
32
- version: '4.2'
26
+ version: 4.2.0
33
27
  - !ruby/object:Gem::Dependency
34
28
  name: connection_pool
35
29
  requirement: !ruby/object:Gem::Requirement
36
30
  requirements:
37
- - - "~>"
38
- - !ruby/object:Gem::Version
39
- version: '2.2'
40
31
  - - ">="
41
32
  - !ruby/object:Gem::Version
42
33
  version: 2.2.2
@@ -44,9 +35,6 @@ dependencies:
44
35
  prerelease: false
45
36
  version_requirements: !ruby/object:Gem::Requirement
46
37
  requirements:
47
- - - "~>"
48
- - !ruby/object:Gem::Version
49
- version: '2.2'
50
38
  - - ">="
51
39
  - !ruby/object:Gem::Version
52
40
  version: 2.2.2
@@ -64,51 +52,41 @@ dependencies:
64
52
  - - "~>"
65
53
  - !ruby/object:Gem::Version
66
54
  version: '2.0'
67
- - !ruby/object:Gem::Dependency
68
- name: rack-protection
69
- requirement: !ruby/object:Gem::Requirement
70
- requirements:
71
- - - ">="
72
- - !ruby/object:Gem::Version
73
- version: 1.5.0
74
- type: :runtime
75
- prerelease: false
76
- version_requirements: !ruby/object:Gem::Requirement
77
- requirements:
78
- - - ">="
79
- - !ruby/object:Gem::Version
80
- version: 1.5.0
81
55
  description: Simple, efficient background processing for Ruby.
82
56
  email:
83
57
  - mperham@gmail.com
84
58
  executables:
85
59
  - sidekiq
86
- - sidekiqctl
60
+ - sidekiqmon
87
61
  extensions: []
88
62
  extra_rdoc_files: []
89
63
  files:
90
- - ".circleci/config.yml"
64
+ - ".github/ISSUE_TEMPLATE/bug_report.md"
91
65
  - ".github/contributing.md"
92
- - ".github/issue_template.md"
66
+ - ".github/workflows/ci.yml"
93
67
  - ".gitignore"
94
- - ".travis.yml"
68
+ - ".standard.yml"
95
69
  - 3.0-Upgrade.md
96
70
  - 4.0-Upgrade.md
97
71
  - 5.0-Upgrade.md
72
+ - 6.0-Upgrade.md
98
73
  - COMM-LICENSE
99
74
  - Changes.md
75
+ - Ent-2.0-Upgrade.md
100
76
  - Ent-Changes.md
101
77
  - Gemfile
78
+ - Gemfile.lock
102
79
  - LICENSE
103
80
  - Pro-2.0-Upgrade.md
104
81
  - Pro-3.0-Upgrade.md
105
82
  - Pro-4.0-Upgrade.md
83
+ - Pro-5.0-Upgrade.md
106
84
  - Pro-Changes.md
107
85
  - README.md
108
86
  - Rakefile
109
87
  - bin/sidekiq
110
- - bin/sidekiqctl
111
88
  - bin/sidekiqload
89
+ - bin/sidekiqmon
112
90
  - code_of_conduct.md
113
91
  - lib/generators/sidekiq/templates/worker.rb.erb
114
92
  - lib/generators/sidekiq/templates/worker_spec.rb.erb
@@ -118,8 +96,6 @@ files:
118
96
  - lib/sidekiq/api.rb
119
97
  - lib/sidekiq/cli.rb
120
98
  - lib/sidekiq/client.rb
121
- - lib/sidekiq/core_ext.rb
122
- - lib/sidekiq/ctl.rb
123
99
  - lib/sidekiq/delay.rb
124
100
  - lib/sidekiq/exception_handler.rb
125
101
  - lib/sidekiq/extensions/action_mailer.rb
@@ -130,16 +106,18 @@ files:
130
106
  - lib/sidekiq/job_logger.rb
131
107
  - lib/sidekiq/job_retry.rb
132
108
  - lib/sidekiq/launcher.rb
133
- - lib/sidekiq/logging.rb
109
+ - lib/sidekiq/logger.rb
134
110
  - lib/sidekiq/manager.rb
135
111
  - lib/sidekiq/middleware/chain.rb
136
112
  - lib/sidekiq/middleware/i18n.rb
137
- - lib/sidekiq/middleware/server/active_record.rb
113
+ - lib/sidekiq/monitor.rb
138
114
  - lib/sidekiq/paginator.rb
139
115
  - lib/sidekiq/processor.rb
140
116
  - lib/sidekiq/rails.rb
141
117
  - lib/sidekiq/redis_connection.rb
142
118
  - lib/sidekiq/scheduled.rb
119
+ - lib/sidekiq/sd_notify.rb
120
+ - lib/sidekiq/systemd.rb
143
121
  - lib/sidekiq/testing.rb
144
122
  - lib/sidekiq/testing/inline.rb
145
123
  - lib/sidekiq/util.rb
@@ -147,6 +125,7 @@ files:
147
125
  - lib/sidekiq/web.rb
148
126
  - lib/sidekiq/web/action.rb
149
127
  - lib/sidekiq/web/application.rb
128
+ - lib/sidekiq/web/csrf_protection.rb
150
129
  - lib/sidekiq/web/helpers.rb
151
130
  - lib/sidekiq/web/router.rb
152
131
  - lib/sidekiq/worker.rb
@@ -156,6 +135,7 @@ files:
156
135
  - web/assets/images/status.png
157
136
  - web/assets/javascripts/application.js
158
137
  - web/assets/javascripts/dashboard.js
138
+ - web/assets/stylesheets/application-dark.css
159
139
  - web/assets/stylesheets/application-rtl.css
160
140
  - web/assets/stylesheets/application.css
161
141
  - web/assets/stylesheets/bootstrap-rtl.min.css
@@ -174,6 +154,7 @@ files:
174
154
  - web/locales/it.yml
175
155
  - web/locales/ja.yml
176
156
  - web/locales/ko.yml
157
+ - web/locales/lt.yml
177
158
  - web/locales/nb.yml
178
159
  - web/locales/nl.yml
179
160
  - web/locales/pl.yml
@@ -184,6 +165,7 @@ files:
184
165
  - web/locales/ta.yml
185
166
  - web/locales/uk.yml
186
167
  - web/locales/ur.yml
168
+ - web/locales/vi.yml
187
169
  - web/locales/zh-cn.yml
188
170
  - web/locales/zh-tw.yml
189
171
  - web/views/_footer.erb
@@ -208,7 +190,7 @@ homepage: http://sidekiq.org
208
190
  licenses:
209
191
  - LGPL-3.0
210
192
  metadata: {}
211
- post_install_message:
193
+ post_install_message:
212
194
  rdoc_options: []
213
195
  require_paths:
214
196
  - lib
@@ -216,7 +198,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
216
198
  requirements:
217
199
  - - ">="
218
200
  - !ruby/object:Gem::Version
219
- version: 2.2.2
201
+ version: 2.5.0
220
202
  required_rubygems_version: !ruby/object:Gem::Requirement
221
203
  requirements:
222
204
  - - ">="
@@ -224,7 +206,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
224
206
  version: '0'
225
207
  requirements: []
226
208
  rubygems_version: 3.1.2
227
- signing_key:
209
+ signing_key:
228
210
  specification_version: 4
229
211
  summary: Simple, efficient background processing for Ruby
230
212
  test_files: []
data/.circleci/config.yml DELETED
@@ -1,61 +0,0 @@
1
- version: 2
2
- references:
3
- unit: &unit
4
- run:
5
- name: Run test suite
6
- command: bundle exec rake
7
- restore: &restore
8
- restore_cache:
9
- keys:
10
- - v1-dependencies-{{ checksum "Gemfile.lock" }}
11
- # fallback to using the latest cache if no exact match is found
12
- - v1-dependencies-
13
- bundle: &bundle
14
- run:
15
- name: install dependencies
16
- command: |
17
- bundle install --jobs=4 --retry=3 --path vendor/bundle
18
- save: &save
19
- save_cache:
20
- paths:
21
- - ./vendor/bundle
22
- key: v1-dependencies-{{ checksum "Gemfile.lock" }}
23
- jobs:
24
- "ruby-2.5":
25
- docker:
26
- - image: circleci/ruby:2.5
27
- - image: circleci/redis:4.0
28
- steps:
29
- - checkout
30
- - <<: *restore
31
- - <<: *bundle
32
- - <<: *save
33
- - <<: *unit
34
- "ruby-2.6":
35
- docker:
36
- - image: circleci/ruby:2.6
37
- - image: circleci/redis:4.0
38
- steps:
39
- - checkout
40
- - <<: *restore
41
- - <<: *bundle
42
- - <<: *save
43
- - <<: *unit
44
- "jruby":
45
- docker:
46
- - image: circleci/jruby:latest
47
- - image: circleci/redis:4.0
48
- steps:
49
- - checkout
50
- - <<: *restore
51
- - <<: *bundle
52
- - <<: *save
53
- - <<: *unit
54
-
55
- workflows:
56
- version: 2
57
- build:
58
- jobs:
59
- - "ruby-2.5"
60
- - "ruby-2.6"
61
- - "jruby"
@@ -1,11 +0,0 @@
1
- Ruby version:
2
- Sidekiq / Pro / Enterprise version(s):
3
-
4
- Please include your initializer and any error message with the full backtrace.
5
-
6
- Are you using an old version?
7
- Have you checked the changelogs to see if your issue has been fixed in a later version?
8
-
9
- https://github.com/mperham/sidekiq/blob/master/Changes.md
10
- https://github.com/mperham/sidekiq/blob/master/Pro-Changes.md
11
- https://github.com/mperham/sidekiq/blob/master/Ent-Changes.md
data/.travis.yml DELETED
@@ -1,11 +0,0 @@
1
- language: ruby
2
- sudo: false
3
- cache: bundler
4
- services:
5
- - redis-server
6
- rvm:
7
- - 2.3.7
8
- - 2.4.4
9
- - 2.5.1
10
- - 2.6.0
11
- - jruby-9.2.6.0
data/bin/sidekiqctl DELETED
@@ -1,20 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require 'fileutils'
4
- require 'sidekiq/api'
5
- require 'sidekiq/ctl'
6
-
7
- if ARGV[0] == 'status'
8
- Sidekiq::Ctl::Status.new.display(ARGV[1])
9
- else
10
- if ARGV.length < 2
11
- Sidekiq::Ctl.print_usage
12
- else
13
- stage = ARGV[0]
14
- pidfile = ARGV[1]
15
- timeout = ARGV[2].to_i
16
- timeout = Sidekiq::Ctl::DEFAULT_KILL_TIMEOUT if timeout == 0
17
-
18
- Sidekiq::Ctl.new(stage, pidfile, timeout)
19
- end
20
- end
@@ -1 +0,0 @@
1
- raise "no longer used, will be removed in 5.1"
data/lib/sidekiq/ctl.rb DELETED
@@ -1,221 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require 'fileutils'
4
- require 'sidekiq/api'
5
-
6
- class Sidekiq::Ctl
7
- DEFAULT_KILL_TIMEOUT = 10
8
- CMD = File.basename($0)
9
-
10
- attr_reader :stage, :pidfile, :kill_timeout
11
-
12
- def self.print_usage
13
- puts "#{CMD} - control Sidekiq from the command line."
14
- puts
15
- puts "Usage: #{CMD} quiet <pidfile> <kill_timeout>"
16
- puts " #{CMD} stop <pidfile> <kill_timeout>"
17
- puts " #{CMD} status <section>"
18
- puts
19
- puts " <pidfile> is path to a pidfile"
20
- puts " <kill_timeout> is number of seconds to wait until Sidekiq exits"
21
- puts " (default: #{Sidekiq::Ctl::DEFAULT_KILL_TIMEOUT}), after which Sidekiq will be KILL'd"
22
- puts
23
- puts " <section> (optional) view a specific section of the status output"
24
- puts " Valid sections are: #{Sidekiq::Ctl::Status::VALID_SECTIONS.join(', ')}"
25
- puts
26
- puts "Be sure to set the kill_timeout LONGER than Sidekiq's -t timeout. If you want"
27
- puts "to wait 60 seconds for jobs to finish, use `sidekiq -t 60` and `sidekiqctl stop"
28
- puts " path_to_pidfile 61`"
29
- puts
30
- end
31
-
32
- def initialize(stage, pidfile, timeout)
33
- @stage = stage
34
- @pidfile = pidfile
35
- @kill_timeout = timeout
36
-
37
- done('No pidfile given', :error) if !pidfile
38
- done("Pidfile #{pidfile} does not exist", :warn) if !File.exist?(pidfile)
39
- done('Invalid pidfile content', :error) if pid == 0
40
-
41
- fetch_process
42
-
43
- begin
44
- send(stage)
45
- rescue NoMethodError
46
- done "Invalid command: #{stage}", :error
47
- end
48
- end
49
-
50
- def fetch_process
51
- Process.kill(0, pid)
52
- rescue Errno::ESRCH
53
- done "Process doesn't exist", :error
54
- # We were not allowed to send a signal, but the process must have existed
55
- # when Process.kill() was called.
56
- rescue Errno::EPERM
57
- return pid
58
- end
59
-
60
- def done(msg, error = nil)
61
- puts msg
62
- exit(exit_signal(error))
63
- end
64
-
65
- def exit_signal(error)
66
- (error == :error) ? 1 : 0
67
- end
68
-
69
- def pid
70
- @pid ||= File.read(pidfile).to_i
71
- end
72
-
73
- def quiet
74
- `kill -TSTP #{pid}`
75
- end
76
-
77
- def stop
78
- `kill -TERM #{pid}`
79
- kill_timeout.times do
80
- begin
81
- Process.kill(0, pid)
82
- rescue Errno::ESRCH
83
- FileUtils.rm_f pidfile
84
- done 'Sidekiq shut down gracefully.'
85
- rescue Errno::EPERM
86
- done 'Not permitted to shut down Sidekiq.'
87
- end
88
- sleep 1
89
- end
90
- `kill -9 #{pid}`
91
- FileUtils.rm_f pidfile
92
- done 'Sidekiq shut down forcefully.'
93
- end
94
- alias_method :shutdown, :stop
95
-
96
- class Status
97
- VALID_SECTIONS = %w[all version overview processes queues]
98
- def display(section = nil)
99
- section ||= 'all'
100
- unless VALID_SECTIONS.include? section
101
- puts "I don't know how to check the status of '#{section}'!"
102
- puts "Try one of these: #{VALID_SECTIONS.join(', ')}"
103
- return
104
- end
105
- send(section)
106
- rescue StandardError => e
107
- puts "Couldn't get status: #{e}"
108
- end
109
-
110
- def all
111
- version
112
- puts
113
- overview
114
- puts
115
- processes
116
- puts
117
- queues
118
- end
119
-
120
- def version
121
- puts "Sidekiq #{Sidekiq::VERSION}"
122
- puts Time.now
123
- end
124
-
125
- def overview
126
- puts '---- Overview ----'
127
- puts " Processed: #{delimit stats.processed}"
128
- puts " Failed: #{delimit stats.failed}"
129
- puts " Busy: #{delimit stats.workers_size}"
130
- puts " Enqueued: #{delimit stats.enqueued}"
131
- puts " Retries: #{delimit stats.retry_size}"
132
- puts " Scheduled: #{delimit stats.scheduled_size}"
133
- puts " Dead: #{delimit stats.dead_size}"
134
- end
135
-
136
- def processes
137
- puts "---- Processes (#{process_set.size}) ----"
138
- process_set.each_with_index do |process, index|
139
- puts "#{process['identity']} #{tags_for(process)}"
140
- puts " Started: #{Time.at(process['started_at'])} (#{time_ago(process['started_at'])})"
141
- puts " Threads: #{process['concurrency']} (#{process['busy']} busy)"
142
- puts " Queues: #{split_multiline(process['queues'].sort, pad: 11)}"
143
- puts '' unless (index+1) == process_set.size
144
- end
145
- end
146
-
147
- COL_PAD = 2
148
- def queues
149
- puts "---- Queues (#{queue_data.size}) ----"
150
- columns = {
151
- name: [:ljust, (['name'] + queue_data.map(&:name)).map(&:length).max + COL_PAD],
152
- size: [:rjust, (['size'] + queue_data.map(&:size)).map(&:length).max + COL_PAD],
153
- latency: [:rjust, (['latency'] + queue_data.map(&:latency)).map(&:length).max + COL_PAD]
154
- }
155
- columns.each { |col, (dir, width)| print col.to_s.upcase.public_send(dir, width) }
156
- puts
157
- queue_data.each do |q|
158
- columns.each do |col, (dir, width)|
159
- print q.send(col).public_send(dir, width)
160
- end
161
- puts
162
- end
163
- end
164
-
165
- private
166
-
167
- def delimit(number)
168
- number.to_s.reverse.scan(/.{1,3}/).join(',').reverse
169
- end
170
-
171
- def split_multiline(values, opts = {})
172
- return 'none' unless values
173
- pad = opts[:pad] || 0
174
- max_length = opts[:max_length] || (80 - pad)
175
- out = []
176
- line = ''
177
- values.each do |value|
178
- if (line.length + value.length) > max_length
179
- out << line
180
- line = ' ' * pad
181
- end
182
- line << value + ', '
183
- end
184
- out << line[0..-3]
185
- out.join("\n")
186
- end
187
-
188
- def tags_for(process)
189
- tags = [
190
- process['tag'],
191
- process['labels'],
192
- (process['quiet'] == 'true' ? 'quiet' : nil)
193
- ].flatten.compact
194
- tags.any? ? "[#{tags.join('] [')}]" : nil
195
- end
196
-
197
- def time_ago(timestamp)
198
- seconds = Time.now - Time.at(timestamp)
199
- return 'just now' if seconds < 60
200
- return 'a minute ago' if seconds < 120
201
- return "#{seconds.floor / 60} minutes ago" if seconds < 3600
202
- return 'an hour ago' if seconds < 7200
203
- "#{seconds.floor / 60 / 60} hours ago"
204
- end
205
-
206
- QUEUE_STRUCT = Struct.new(:name, :size, :latency)
207
- def queue_data
208
- @queue_data ||= Sidekiq::Queue.all.map do |q|
209
- QUEUE_STRUCT.new(q.name, q.size.to_s, sprintf('%#.2f', q.latency))
210
- end
211
- end
212
-
213
- def process_set
214
- @process_set ||= Sidekiq::ProcessSet.new
215
- end
216
-
217
- def stats
218
- @stats ||= Sidekiq::Stats.new
219
- end
220
- end
221
- end