sidekiq 6.0.2 → 6.0.7

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.

@@ -62,7 +62,7 @@ class Sidekiq::Monitor
62
62
  columns = {
63
63
  name: [:ljust, (["name"] + queue_data.map(&:name)).map(&:length).max + COL_PAD],
64
64
  size: [:rjust, (["size"] + queue_data.map(&:size)).map(&:length).max + COL_PAD],
65
- latency: [:rjust, (["latency"] + queue_data.map(&:latency)).map(&:length).max + COL_PAD],
65
+ latency: [:rjust, (["latency"] + queue_data.map(&:latency)).map(&:length).max + COL_PAD]
66
66
  }
67
67
  columns.each { |col, (dir, width)| print col.to_s.upcase.public_send(dir, width) }
68
68
  puts
@@ -101,7 +101,7 @@ class Sidekiq::Monitor
101
101
  tags = [
102
102
  process["tag"],
103
103
  process["labels"],
104
- (process["quiet"] == "true" ? "quiet" : nil),
104
+ (process["quiet"] == "true" ? "quiet" : nil)
105
105
  ].flatten.compact
106
106
  tags.any? ? "[#{tags.join("] [")}]" : nil
107
107
  end
@@ -181,7 +181,7 @@ module Sidekiq
181
181
  # the retry subsystem (e.g. network partition). We won't acknowledge the job
182
182
  # so it can be rescued when using Sidekiq Pro.
183
183
  handle_exception(ex, {context: "Internal exception!", job: job_hash, jobstr: jobstr})
184
- raise e
184
+ raise ex
185
185
  ensure
186
186
  if ack
187
187
  # We don't want a shutdown signal to interrupt job acknowledgment.
@@ -12,8 +12,9 @@ module Sidekiq
12
12
  options[key.to_sym] = options.delete(key)
13
13
  end
14
14
 
15
- options[:id] = "Sidekiq-#{Sidekiq.server? ? "server" : "client"}-PID-#{::Process.pid}" unless options.key?(:id)
16
- options[:url] ||= determine_redis_provider
15
+ if !options[:url] && (u = determine_redis_provider)
16
+ options[:url] = u
17
+ end
17
18
 
18
19
  size = if options[:size]
19
20
  options[:size]
@@ -93,9 +94,10 @@ module Sidekiq
93
94
  end
94
95
 
95
96
  def log_info(options)
96
- # Don't log Redis AUTH password
97
97
  redacted = "REDACTED"
98
- scrubbed_options = options.dup
98
+
99
+ # deep clone so we can muck with these options all we want
100
+ scrubbed_options = Marshal.load(Marshal.dump(options))
99
101
  if scrubbed_options[:url] && (uri = URI.parse(scrubbed_options[:url])) && uri.password
100
102
  uri.password = redacted
101
103
  scrubbed_options[:url] = uri.to_s
@@ -103,6 +105,9 @@ module Sidekiq
103
105
  if scrubbed_options[:password]
104
106
  scrubbed_options[:password] = redacted
105
107
  end
108
+ scrubbed_options[:sentinels]&.each do |sentinel|
109
+ sentinel[:password] = redacted if sentinel[:password]
110
+ end
106
111
  if Sidekiq.server?
107
112
  Sidekiq.logger.info("Booting Sidekiq #{Sidekiq::VERSION} with redis options #{scrubbed_options}")
108
113
  else
@@ -0,0 +1,149 @@
1
+ # frozen_string_literal: true
2
+
3
+ # The MIT License
4
+ #
5
+ # Copyright (c) 2017, 2018, 2019, 2020 Agis Anastasopoulos
6
+ #
7
+ # Permission is hereby granted, free of charge, to any person obtaining a copy of
8
+ # this software and associated documentation files (the "Software"), to deal in
9
+ # the Software without restriction, including without limitation the rights to
10
+ # use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
11
+ # the Software, and to permit persons to whom the Software is furnished to do so,
12
+ # subject to the following conditions:
13
+ #
14
+ # The above copyright notice and this permission notice shall be included in all
15
+ # copies or substantial portions of the Software.
16
+ #
17
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
19
+ # FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
20
+ # COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
21
+ # IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22
+ # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
+
24
+ # This is a copy of https://github.com/agis/ruby-sdnotify as of commit a7d52ee
25
+ # The only changes made was "rehoming" it within the Sidekiq module to avoid
26
+ # namespace collisions and applying standard's code formatting style.
27
+
28
+ require "socket"
29
+
30
+ # SdNotify is a pure-Ruby implementation of sd_notify(3). It can be used to
31
+ # notify systemd about state changes. Methods of this package are no-op on
32
+ # non-systemd systems (eg. Darwin).
33
+ #
34
+ # The API maps closely to the original implementation of sd_notify(3),
35
+ # therefore be sure to check the official man pages prior to using SdNotify.
36
+ #
37
+ # @see https://www.freedesktop.org/software/systemd/man/sd_notify.html
38
+ module Sidekiq
39
+ module SdNotify
40
+ # Exception raised when there's an error writing to the notification socket
41
+ class NotifyError < RuntimeError; end
42
+
43
+ READY = "READY=1"
44
+ RELOADING = "RELOADING=1"
45
+ STOPPING = "STOPPING=1"
46
+ STATUS = "STATUS="
47
+ ERRNO = "ERRNO="
48
+ MAINPID = "MAINPID="
49
+ WATCHDOG = "WATCHDOG=1"
50
+ FDSTORE = "FDSTORE=1"
51
+
52
+ def self.ready(unset_env = false)
53
+ notify(READY, unset_env)
54
+ end
55
+
56
+ def self.reloading(unset_env = false)
57
+ notify(RELOADING, unset_env)
58
+ end
59
+
60
+ def self.stopping(unset_env = false)
61
+ notify(STOPPING, unset_env)
62
+ end
63
+
64
+ # @param status [String] a custom status string that describes the current
65
+ # state of the service
66
+ def self.status(status, unset_env = false)
67
+ notify("#{STATUS}#{status}", unset_env)
68
+ end
69
+
70
+ # @param errno [Integer]
71
+ def self.errno(errno, unset_env = false)
72
+ notify("#{ERRNO}#{errno}", unset_env)
73
+ end
74
+
75
+ # @param pid [Integer]
76
+ def self.mainpid(pid, unset_env = false)
77
+ notify("#{MAINPID}#{pid}", unset_env)
78
+ end
79
+
80
+ def self.watchdog(unset_env = false)
81
+ notify(WATCHDOG, unset_env)
82
+ end
83
+
84
+ def self.fdstore(unset_env = false)
85
+ notify(FDSTORE, unset_env)
86
+ end
87
+
88
+ # @param [Boolean] true if the service manager expects watchdog keep-alive
89
+ # notification messages to be sent from this process.
90
+ #
91
+ # If the $WATCHDOG_USEC environment variable is set,
92
+ # and the $WATCHDOG_PID variable is unset or set to the PID of the current
93
+ # process
94
+ #
95
+ # @note Unlike sd_watchdog_enabled(3), this method does not mutate the
96
+ # environment.
97
+ def self.watchdog?
98
+ wd_usec = ENV["WATCHDOG_USEC"]
99
+ wd_pid = ENV["WATCHDOG_PID"]
100
+
101
+ return false unless wd_usec
102
+
103
+ begin
104
+ wd_usec = Integer(wd_usec)
105
+ rescue
106
+ return false
107
+ end
108
+
109
+ return false if wd_usec <= 0
110
+ return true if !wd_pid || wd_pid == $$.to_s
111
+
112
+ false
113
+ end
114
+
115
+ # Notify systemd with the provided state, via the notification socket, if
116
+ # any.
117
+ #
118
+ # Generally this method will be used indirectly through the other methods
119
+ # of the library.
120
+ #
121
+ # @param state [String]
122
+ # @param unset_env [Boolean]
123
+ #
124
+ # @return [Fixnum, nil] the number of bytes written to the notification
125
+ # socket or nil if there was no socket to report to (eg. the program wasn't
126
+ # started by systemd)
127
+ #
128
+ # @raise [NotifyError] if there was an error communicating with the systemd
129
+ # socket
130
+ #
131
+ # @see https://www.freedesktop.org/software/systemd/man/sd_notify.html
132
+ def self.notify(state, unset_env = false)
133
+ sock = ENV["NOTIFY_SOCKET"]
134
+
135
+ return nil unless sock
136
+
137
+ ENV.delete("NOTIFY_SOCKET") if unset_env
138
+
139
+ begin
140
+ Addrinfo.unix(sock, :DGRAM).connect do |s|
141
+ s.close_on_exec = true
142
+ s.write(state)
143
+ end
144
+ rescue => e
145
+ raise NotifyError, "#{e.class}: #{e.message}", e.backtrace
146
+ end
147
+ end
148
+ end
149
+ end
@@ -0,0 +1,24 @@
1
+ #
2
+ # Sidekiq's systemd integration allows Sidekiq to inform systemd:
3
+ # 1. when it has successfully started
4
+ # 2. when it is starting shutdown
5
+ # 3. periodically for a liveness check with a watchdog thread
6
+ #
7
+ module Sidekiq
8
+ def self.start_watchdog
9
+ usec = Integer(ENV["WATCHDOG_USEC"])
10
+ return Sidekiq.logger.error("systemd Watchdog too fast: " + usec) if usec < 1_000_000
11
+
12
+ sec_f = usec / 1_000_000.0
13
+ # "It is recommended that a daemon sends a keep-alive notification message
14
+ # to the service manager every half of the time returned here."
15
+ ping_f = sec_f / 2
16
+ Sidekiq.logger.info "Pinging systemd watchdog every #{ping_f.round(1)} sec"
17
+ Thread.new do
18
+ loop do
19
+ sleep ping_f
20
+ Sidekiq::SdNotify.watchdog
21
+ end
22
+ end
23
+ end
24
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Sidekiq
4
- VERSION = "6.0.2"
4
+ VERSION = "6.0.7"
5
5
  end
@@ -31,7 +31,7 @@ module Sidekiq
31
31
  "Queues" => "queues",
32
32
  "Retries" => "retries",
33
33
  "Scheduled" => "scheduled",
34
- "Dead" => "morgue",
34
+ "Dead" => "morgue"
35
35
  }
36
36
 
37
37
  class << self
@@ -19,7 +19,7 @@ module Sidekiq
19
19
  "script-src 'self' https: http: 'unsafe-inline'",
20
20
  "style-src 'self' https: http: 'unsafe-inline'",
21
21
  "worker-src 'self'",
22
- "base-uri 'self'",
22
+ "base-uri 'self'"
23
23
  ].join("; ").freeze
24
24
 
25
25
  def initialize(klass)
@@ -90,7 +90,15 @@ module Sidekiq
90
90
  end
91
91
 
92
92
  post "/queues/:name" do
93
- Sidekiq::Queue.new(route_params[:name]).clear
93
+ queue = Sidekiq::Queue.new(route_params[:name])
94
+
95
+ if Sidekiq.pro? && params["pause"]
96
+ queue.pause!
97
+ elsif Sidekiq.pro? && params["unpause"]
98
+ queue.unpause!
99
+ else
100
+ queue.clear
101
+ end
94
102
 
95
103
  redirect "#{root_path}queues"
96
104
  end
@@ -267,7 +275,7 @@ module Sidekiq
267
275
  scheduled: sidekiq_stats.scheduled_size,
268
276
  retries: sidekiq_stats.retry_size,
269
277
  dead: sidekiq_stats.dead_size,
270
- default_latency: sidekiq_stats.default_queue_latency,
278
+ default_latency: sidekiq_stats.default_queue_latency
271
279
  },
272
280
  redis: redis_stats,
273
281
  server_utc_time: server_utc_time
@@ -292,22 +300,20 @@ module Sidekiq
292
300
 
293
301
  resp = case resp
294
302
  when Array
303
+ # redirects go here
295
304
  resp
296
305
  else
306
+ # rendered content goes here
297
307
  headers = {
298
308
  "Content-Type" => "text/html",
299
309
  "Cache-Control" => "no-cache",
300
310
  "Content-Language" => action.locale,
301
- "Content-Security-Policy" => CSP_HEADER,
311
+ "Content-Security-Policy" => CSP_HEADER
302
312
  }
303
-
313
+ # we'll let Rack calculate Content-Length for us.
304
314
  [200, headers, [resp]]
305
315
  end
306
316
 
307
- resp[1] = resp[1].dup
308
-
309
- resp[1][CONTENT_LENGTH] = resp[2].sum(&:bytesize).to_s
310
-
311
317
  resp
312
318
  end
313
319
 
@@ -295,7 +295,7 @@ module Sidekiq
295
295
  end
296
296
 
297
297
  def environment_title_prefix
298
- environment = Sidekiq.options[:environment] || ENV["RAILS_ENV"] || ENV["RACK_ENV"] || "development"
298
+ environment = Sidekiq.options[:environment] || ENV["APP_ENV"] || ENV["RAILS_ENV"] || ENV["RACK_ENV"] || "development"
299
299
 
300
300
  "[#{environment.upcase}] " unless environment == "production"
301
301
  end
@@ -94,9 +94,7 @@ module Sidekiq
94
94
  {} if path == matcher
95
95
  else
96
96
  path_match = path.match(matcher)
97
- if path_match
98
- Hash[path_match.names.map(&:to_sym).zip(path_match.captures)]
99
- end
97
+ path_match&.named_captures&.transform_keys(&:to_sym)
100
98
  end
101
99
  end
102
100
  end
@@ -48,8 +48,8 @@ module Sidekiq
48
48
  # In practice, any option is allowed. This is the main mechanism to configure the
49
49
  # options for a specific job.
50
50
  def sidekiq_options(opts = {})
51
- opts = Hash[opts.map { |k, v| [k.to_s, v] }] # stringify
52
- self.sidekiq_options_hash = get_sidekiq_options.merge(Hash[opts.map { |k, v| [k.to_s, v] }])
51
+ opts = opts.transform_keys(&:to_s) # stringify
52
+ self.sidekiq_options_hash = get_sidekiq_options.merge(opts)
53
53
  end
54
54
 
55
55
  def sidekiq_retry_in(&block)
@@ -16,6 +16,6 @@ Gem::Specification.new do |gem|
16
16
 
17
17
  gem.add_dependency "redis", ">= 4.1.0"
18
18
  gem.add_dependency "connection_pool", ">= 2.2.2"
19
- gem.add_dependency "rack", ">= 2.0.0"
19
+ gem.add_dependency "rack", "~> 2.0"
20
20
  gem.add_dependency "rack-protection", ">= 2.0.0"
21
21
  end
@@ -19,7 +19,8 @@ Sidekiq = {};
19
19
  $(function() {
20
20
  var pollpath = $('body').data('poll-path');
21
21
  if (pollpath != "") {
22
- updatePage(pollpath);
22
+ var ti = parseInt(localStorage.timeInterval) || 2000;
23
+ setTimeout(function(){updatePage(pollpath)}, ti);
23
24
  }
24
25
 
25
26
  $(document).on('click', '.check_all', function() {
@@ -55,26 +56,28 @@ function updateFuzzyTimes(locale) {
55
56
  }
56
57
 
57
58
  function updatePage(url) {
58
- setInterval(function () {
59
- $.ajax({
60
- url: url,
61
- dataType: 'html'
62
- }).done(function (data) {
63
- $data = $(data)
64
-
65
- var $page = $data.filter('#page')
66
- $('#page').replaceWith($page)
67
-
68
- var $header_status = $data.find('.status')
69
- $('.status').replaceWith($header_status)
70
-
71
- updateFuzzyTimes($('body').data('locale'));
72
- })
73
- }, parseInt(localStorage.timeInterval) || 2000);
59
+ $.ajax({
60
+ url: url,
61
+ dataType: 'html'
62
+ }).done(function(data) {
63
+ $data = $(data)
64
+
65
+ var $page = $data.filter('#page')
66
+ $('#page').replaceWith($page)
67
+
68
+ var $header_status = $data.find('.status')
69
+ $('.status').replaceWith($header_status)
70
+
71
+ updateFuzzyTimes($('body').data('locale'));
72
+
73
+ var ti = parseInt(localStorage.timeInterval) || 2000;
74
+ setTimeout(function(){updatePage(url)}, ti)
75
+ }).fail(function() {
76
+ var ti = parseInt(localStorage.timeInterval) || 2000;
77
+ setTimeout(function(){updatePage(url)}, ti)
78
+ })
74
79
  }
75
80
 
76
-
77
-
78
81
  $(function() {
79
82
  'use strict';
80
83
 
@@ -1,125 +1,122 @@
1
- @media (prefers-color-scheme: dark) {
2
-
3
- body {
4
- background-color: #000;
5
- color: #ccc;
6
- }
7
-
8
- a,
9
- .title,
10
- .summary_bar ul .count,
11
- .navbar .navbar-brand {
12
- color: #af0014;
13
- }
14
-
15
- .navbar .navbar-brand:hover {
16
- color: #ccc;
17
- }
18
-
19
- .navbar .navbar-brand .status {
20
- color: #ccc;
21
- }
22
-
23
- .navbar-inverse {
24
- background-color: #000;
25
- border-color: #333;
26
- }
27
-
28
- table.table-white {
29
- background-color: #111;
30
- }
31
-
32
- .table-striped > tbody > tr:nth-of-type(odd) {
33
- background-color: #222;
34
- }
35
-
36
- .table-bordered,
37
- .table-bordered > tbody > tr > td,
38
- .table-bordered > tbody > tr > th,
39
- .table-bordered > tfoot > tr > td,
40
- .table-bordered > tfoot > tr > th,
41
- .table-bordered > thead > tr > td,
42
- .table-bordered > thead > tr > th {
43
- border: 1px solid #333;
44
- }
45
-
46
- .table-hover > tbody > tr:hover {
47
- background-color: #333;
48
- }
49
-
50
- .alert {
51
- border: none;
52
- color: #ccc;
53
- }
54
-
55
- .alert-success {
56
- background-color: #000;
57
- }
58
-
59
- a:link,
60
- a:active,
61
- a:hover,
62
- a:visited {
63
- color: #63798c;
64
- }
65
-
66
- a.btn {
67
- color: #000;
68
- }
69
-
70
- .summary_bar .summary {
71
- background-color: #000;
72
- border: 1px solid #333;
73
- }
74
-
75
- .navbar-default {
76
- background-color: #000;
77
- border-color: #3d3d3d;
78
- }
79
-
80
- .navbar-default .navbar-nav > .active > a,
81
- .navbar-default .navbar-nav > .active > a:focus,
82
- .navbar-default .navbar-nav > .active > a:hover {
83
- color: #ccc;
84
- background-color: #282828;
85
- }
86
-
87
- .navbar-default .navbar-nav > li > a:hover {
88
- color: #ccc;
89
- }
90
-
91
- .pagination > li > a,
92
- .pagination > li > a:hover,
93
- .pagination > li > span {
94
- color: #ccc;
95
- background-color: #282828;
96
- border-color: #353535;
97
- }
98
- .pagination > .disabled > a,
99
- .pagination > .disabled > a:focus,
100
- .pagination > .disabled > a:hover,
101
- .pagination > .disabled > span,
102
- .pagination > .disabled > span:focus,
103
- .pagination > .disabled > span:hover {
104
- color: #a5a5a5;
105
- background-color: #282828;
106
- border-color: #353535;
107
- }
108
-
109
- .stat {
110
- border: 1px solid rgba(255, 255, 255, 0.1);
111
- }
112
-
113
- #live-poll {
114
- color: #ccc;
115
- }
116
-
117
- .btn-warn {
118
- color: #333;
119
- }
120
-
121
- .rickshaw_graph .y_ticks.glow text {
122
- fill: #ccc;
123
- color: #ccc;
124
- }
1
+ body {
2
+ background-color: #000;
3
+ color: #ccc;
4
+ }
5
+
6
+ a,
7
+ .title,
8
+ .summary_bar ul .count,
9
+ .navbar .navbar-brand {
10
+ color: #af0014;
11
+ }
12
+
13
+ .navbar .navbar-brand:hover {
14
+ color: #ccc;
15
+ }
16
+
17
+ .navbar .navbar-brand .status {
18
+ color: #ccc;
19
+ }
20
+
21
+ .navbar-inverse {
22
+ background-color: #000;
23
+ border-color: #333;
24
+ }
25
+
26
+ table.table-white {
27
+ background-color: #111;
28
+ }
29
+
30
+ .table-striped > tbody > tr:nth-of-type(odd) {
31
+ background-color: #222;
32
+ }
33
+
34
+ .table-bordered,
35
+ .table-bordered > tbody > tr > td,
36
+ .table-bordered > tbody > tr > th,
37
+ .table-bordered > tfoot > tr > td,
38
+ .table-bordered > tfoot > tr > th,
39
+ .table-bordered > thead > tr > td,
40
+ .table-bordered > thead > tr > th {
41
+ border: 1px solid #333;
42
+ }
43
+
44
+ .table-hover > tbody > tr:hover {
45
+ background-color: #333;
46
+ }
47
+
48
+ .alert {
49
+ border: none;
50
+ color: #ccc;
51
+ }
52
+
53
+ .alert-success {
54
+ background-color: #000;
55
+ }
56
+
57
+ a:link,
58
+ a:active,
59
+ a:hover,
60
+ a:visited {
61
+ color: #63798c;
62
+ }
63
+
64
+ a.btn {
65
+ color: #000;
66
+ }
67
+
68
+ .summary_bar .summary {
69
+ background-color: #000;
70
+ border: 1px solid #333;
71
+ }
72
+
73
+ .navbar-default {
74
+ background-color: #000;
75
+ border-color: #3d3d3d;
76
+ }
77
+
78
+ .navbar-default .navbar-nav > .active > a,
79
+ .navbar-default .navbar-nav > .active > a:focus,
80
+ .navbar-default .navbar-nav > .active > a:hover {
81
+ color: #ccc;
82
+ background-color: #282828;
83
+ }
84
+
85
+ .navbar-default .navbar-nav > li > a:hover {
86
+ color: #ccc;
87
+ }
88
+
89
+ .pagination > li > a,
90
+ .pagination > li > a:hover,
91
+ .pagination > li > span {
92
+ color: #ccc;
93
+ background-color: #282828;
94
+ border-color: #353535;
95
+ }
96
+ .pagination > .disabled > a,
97
+ .pagination > .disabled > a:focus,
98
+ .pagination > .disabled > a:hover,
99
+ .pagination > .disabled > span,
100
+ .pagination > .disabled > span:focus,
101
+ .pagination > .disabled > span:hover {
102
+ color: #a5a5a5;
103
+ background-color: #282828;
104
+ border-color: #353535;
105
+ }
106
+
107
+ .stat {
108
+ border: 1px solid rgba(255, 255, 255, 0.1);
109
+ }
110
+
111
+ #live-poll {
112
+ color: #ccc;
113
+ }
114
+
115
+ .btn-warn {
116
+ color: #333;
117
+ }
118
+
119
+ .rickshaw_graph .y_ticks.glow text {
120
+ fill: #ccc;
121
+ color: #ccc;
125
122
  }