sidekiq 6.4.2 → 6.5.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.
- checksums.yaml +4 -4
- data/Changes.md +35 -0
- data/bin/sidekiqload +15 -3
- data/lib/sidekiq/api.rb +160 -32
- data/lib/sidekiq/cli.rb +34 -32
- data/lib/sidekiq/client.rb +4 -4
- data/lib/sidekiq/component.rb +65 -0
- data/lib/sidekiq/delay.rb +1 -1
- data/lib/sidekiq/fetch.rb +16 -14
- data/lib/sidekiq/job_retry.rb +50 -34
- data/lib/sidekiq/job_util.rb +7 -3
- data/lib/sidekiq/launcher.rb +22 -19
- data/lib/sidekiq/logger.rb +1 -1
- data/lib/sidekiq/manager.rb +23 -20
- data/lib/sidekiq/metrics/deploy.rb +47 -0
- data/lib/sidekiq/metrics/query.rb +124 -0
- data/lib/sidekiq/metrics/shared.rb +94 -0
- data/lib/sidekiq/metrics/tracking.rb +134 -0
- data/lib/sidekiq/middleware/chain.rb +82 -38
- data/lib/sidekiq/middleware/current_attributes.rb +10 -4
- data/lib/sidekiq/middleware/i18n.rb +2 -0
- data/lib/sidekiq/middleware/modules.rb +21 -0
- data/lib/sidekiq/paginator.rb +2 -2
- data/lib/sidekiq/processor.rb +13 -13
- data/lib/sidekiq/rails.rb +5 -5
- data/lib/sidekiq/redis_client_adapter.rb +154 -0
- data/lib/sidekiq/redis_connection.rb +80 -47
- data/lib/sidekiq/ring_buffer.rb +29 -0
- data/lib/sidekiq/scheduled.rb +11 -10
- data/lib/sidekiq/testing.rb +1 -1
- data/lib/sidekiq/transaction_aware_client.rb +45 -0
- data/lib/sidekiq/version.rb +1 -1
- data/lib/sidekiq/web/application.rb +13 -0
- data/lib/sidekiq/web/helpers.rb +25 -2
- data/lib/sidekiq/web.rb +4 -0
- data/lib/sidekiq/worker.rb +2 -1
- data/lib/sidekiq.rb +87 -18
- data/sidekiq.gemspec +1 -1
- data/web/assets/javascripts/application.js +1 -1
- data/web/assets/javascripts/dashboard.js +0 -17
- data/web/assets/javascripts/graph.js +16 -0
- data/web/locales/en.yml +4 -0
- data/web/locales/pt-br.yml +27 -9
- data/web/views/_nav.erb +1 -1
- data/web/views/busy.erb +1 -1
- data/web/views/dashboard.erb +1 -0
- data/web/views/metrics.erb +59 -0
- data/web/views/metrics_for_job.erb +92 -0
- data/web/views/queue.erb +5 -1
- metadata +16 -6
- data/lib/sidekiq/exception_handler.rb +0 -27
- data/lib/sidekiq/util.rb +0 -108
@@ -5,8 +5,81 @@ require "redis"
|
|
5
5
|
require "uri"
|
6
6
|
|
7
7
|
module Sidekiq
|
8
|
-
|
8
|
+
module RedisConnection
|
9
|
+
class RedisAdapter
|
10
|
+
BaseError = Redis::BaseError
|
11
|
+
CommandError = Redis::CommandError
|
12
|
+
|
13
|
+
def initialize(options)
|
14
|
+
warn("Usage of the 'redis' gem within Sidekiq itself is deprecated, Sidekiq 7.0 will only use the new, simpler 'redis-client' gem", caller) if ENV["SIDEKIQ_REDIS_CLIENT"] == "1"
|
15
|
+
@options = options
|
16
|
+
end
|
17
|
+
|
18
|
+
def new_client
|
19
|
+
namespace = @options[:namespace]
|
20
|
+
|
21
|
+
client = Redis.new client_opts(@options)
|
22
|
+
if namespace
|
23
|
+
begin
|
24
|
+
require "redis/namespace"
|
25
|
+
Redis::Namespace.new(namespace, redis: client)
|
26
|
+
rescue LoadError
|
27
|
+
Sidekiq.logger.error("Your Redis configuration uses the namespace '#{namespace}' but the redis-namespace gem is not included in the Gemfile." \
|
28
|
+
"Add the gem to your Gemfile to continue using a namespace. Otherwise, remove the namespace parameter.")
|
29
|
+
exit(-127)
|
30
|
+
end
|
31
|
+
else
|
32
|
+
client
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def client_opts(options)
|
39
|
+
opts = options.dup
|
40
|
+
if opts[:namespace]
|
41
|
+
opts.delete(:namespace)
|
42
|
+
end
|
43
|
+
|
44
|
+
if opts[:network_timeout]
|
45
|
+
opts[:timeout] = opts[:network_timeout]
|
46
|
+
opts.delete(:network_timeout)
|
47
|
+
end
|
48
|
+
|
49
|
+
opts[:driver] ||= Redis::Connection.drivers.last || "ruby"
|
50
|
+
|
51
|
+
# Issue #3303, redis-rb will silently retry an operation.
|
52
|
+
# This can lead to duplicate jobs if Sidekiq::Client's LPUSH
|
53
|
+
# is performed twice but I believe this is much, much rarer
|
54
|
+
# than the reconnect silently fixing a problem; we keep it
|
55
|
+
# on by default.
|
56
|
+
opts[:reconnect_attempts] ||= 1
|
57
|
+
|
58
|
+
opts
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
@adapter = RedisAdapter
|
63
|
+
|
9
64
|
class << self
|
65
|
+
attr_reader :adapter
|
66
|
+
|
67
|
+
# RedisConnection.adapter = :redis
|
68
|
+
# RedisConnection.adapter = :redis_client
|
69
|
+
def adapter=(adapter)
|
70
|
+
raise "no" if adapter == self
|
71
|
+
result = case adapter
|
72
|
+
when :redis
|
73
|
+
RedisAdapter
|
74
|
+
when Class
|
75
|
+
adapter
|
76
|
+
else
|
77
|
+
require "sidekiq/#{adapter}_adapter"
|
78
|
+
nil
|
79
|
+
end
|
80
|
+
@adapter = result if result
|
81
|
+
end
|
82
|
+
|
10
83
|
def create(options = {})
|
11
84
|
symbolized_options = options.transform_keys(&:to_sym)
|
12
85
|
|
@@ -19,20 +92,21 @@ module Sidekiq
|
|
19
92
|
elsif Sidekiq.server?
|
20
93
|
# Give ourselves plenty of connections. pool is lazy
|
21
94
|
# so we won't create them until we need them.
|
22
|
-
Sidekiq
|
95
|
+
Sidekiq[:concurrency] + 5
|
23
96
|
elsif ENV["RAILS_MAX_THREADS"]
|
24
97
|
Integer(ENV["RAILS_MAX_THREADS"])
|
25
98
|
else
|
26
99
|
5
|
27
100
|
end
|
28
101
|
|
29
|
-
verify_sizing(size, Sidekiq
|
102
|
+
verify_sizing(size, Sidekiq[:concurrency]) if Sidekiq.server?
|
30
103
|
|
31
104
|
pool_timeout = symbolized_options[:pool_timeout] || 1
|
32
105
|
log_info(symbolized_options)
|
33
106
|
|
107
|
+
redis_config = adapter.new(symbolized_options)
|
34
108
|
ConnectionPool.new(timeout: pool_timeout, size: size) do
|
35
|
-
|
109
|
+
redis_config.new_client
|
36
110
|
end
|
37
111
|
end
|
38
112
|
|
@@ -50,47 +124,6 @@ module Sidekiq
|
|
50
124
|
raise ArgumentError, "Your Redis connection pool is too small for Sidekiq. Your pool has #{size} connections but must have at least #{concurrency + 2}" if size < (concurrency + 2)
|
51
125
|
end
|
52
126
|
|
53
|
-
def build_client(options)
|
54
|
-
namespace = options[:namespace]
|
55
|
-
|
56
|
-
client = Redis.new client_opts(options)
|
57
|
-
if namespace
|
58
|
-
begin
|
59
|
-
require "redis/namespace"
|
60
|
-
Redis::Namespace.new(namespace, redis: client)
|
61
|
-
rescue LoadError
|
62
|
-
Sidekiq.logger.error("Your Redis configuration uses the namespace '#{namespace}' but the redis-namespace gem is not included in the Gemfile." \
|
63
|
-
"Add the gem to your Gemfile to continue using a namespace. Otherwise, remove the namespace parameter.")
|
64
|
-
exit(-127)
|
65
|
-
end
|
66
|
-
else
|
67
|
-
client
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
def client_opts(options)
|
72
|
-
opts = options.dup
|
73
|
-
if opts[:namespace]
|
74
|
-
opts.delete(:namespace)
|
75
|
-
end
|
76
|
-
|
77
|
-
if opts[:network_timeout]
|
78
|
-
opts[:timeout] = opts[:network_timeout]
|
79
|
-
opts.delete(:network_timeout)
|
80
|
-
end
|
81
|
-
|
82
|
-
opts[:driver] ||= Redis::Connection.drivers.last || "ruby"
|
83
|
-
|
84
|
-
# Issue #3303, redis-rb will silently retry an operation.
|
85
|
-
# This can lead to duplicate jobs if Sidekiq::Client's LPUSH
|
86
|
-
# is performed twice but I believe this is much, much rarer
|
87
|
-
# than the reconnect silently fixing a problem; we keep it
|
88
|
-
# on by default.
|
89
|
-
opts[:reconnect_attempts] ||= 1
|
90
|
-
|
91
|
-
opts
|
92
|
-
end
|
93
|
-
|
94
127
|
def log_info(options)
|
95
128
|
redacted = "REDACTED"
|
96
129
|
|
@@ -110,9 +143,9 @@ module Sidekiq
|
|
110
143
|
sentinel[:password] = redacted if sentinel[:password]
|
111
144
|
end
|
112
145
|
if Sidekiq.server?
|
113
|
-
Sidekiq.logger.info("Booting Sidekiq #{Sidekiq::VERSION} with
|
146
|
+
Sidekiq.logger.info("Booting Sidekiq #{Sidekiq::VERSION} with #{adapter.name} options #{scrubbed_options}")
|
114
147
|
else
|
115
|
-
Sidekiq.logger.debug("#{Sidekiq::NAME} client with
|
148
|
+
Sidekiq.logger.debug("#{Sidekiq::NAME} client with #{adapter.name} options #{scrubbed_options}")
|
116
149
|
end
|
117
150
|
end
|
118
151
|
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require "forwardable"
|
2
|
+
|
3
|
+
module Sidekiq
|
4
|
+
class RingBuffer
|
5
|
+
include Enumerable
|
6
|
+
extend Forwardable
|
7
|
+
def_delegators :@buf, :[], :each, :size
|
8
|
+
|
9
|
+
def initialize(size, default = 0)
|
10
|
+
@size = size
|
11
|
+
@buf = Array.new(size, default)
|
12
|
+
@index = 0
|
13
|
+
end
|
14
|
+
|
15
|
+
def <<(element)
|
16
|
+
@buf[@index % @size] = element
|
17
|
+
@index += 1
|
18
|
+
element
|
19
|
+
end
|
20
|
+
|
21
|
+
def buffer
|
22
|
+
@buf
|
23
|
+
end
|
24
|
+
|
25
|
+
def reset(default = 0)
|
26
|
+
@buf.fill(default)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/lib/sidekiq/scheduled.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "sidekiq"
|
4
|
-
require "sidekiq/util"
|
5
4
|
require "sidekiq/api"
|
5
|
+
require "sidekiq/component"
|
6
6
|
|
7
7
|
module Sidekiq
|
8
8
|
module Scheduled
|
@@ -52,8 +52,8 @@ module Sidekiq
|
|
52
52
|
@lua_zpopbyscore_sha = raw_conn.script(:load, LUA_ZPOPBYSCORE)
|
53
53
|
end
|
54
54
|
|
55
|
-
conn.evalsha(@lua_zpopbyscore_sha, keys
|
56
|
-
rescue
|
55
|
+
conn.evalsha(@lua_zpopbyscore_sha, keys, argv)
|
56
|
+
rescue RedisConnection.adapter::CommandError => e
|
57
57
|
raise unless e.message.start_with?("NOSCRIPT")
|
58
58
|
|
59
59
|
@lua_zpopbyscore_sha = nil
|
@@ -67,12 +67,13 @@ module Sidekiq
|
|
67
67
|
# just pops the job back onto its original queue so the
|
68
68
|
# workers can pick it up like any other job.
|
69
69
|
class Poller
|
70
|
-
include
|
70
|
+
include Sidekiq::Component
|
71
71
|
|
72
72
|
INITIAL_WAIT = 10
|
73
73
|
|
74
|
-
def initialize
|
75
|
-
@
|
74
|
+
def initialize(options)
|
75
|
+
@config = options
|
76
|
+
@enq = (options[:scheduled_enq] || Sidekiq::Scheduled::Enq).new
|
76
77
|
@sleeper = ConnectionPool::TimedStack.new
|
77
78
|
@done = false
|
78
79
|
@thread = nil
|
@@ -100,7 +101,7 @@ module Sidekiq
|
|
100
101
|
enqueue
|
101
102
|
wait
|
102
103
|
end
|
103
|
-
|
104
|
+
logger.info("Scheduler exiting...")
|
104
105
|
}
|
105
106
|
end
|
106
107
|
|
@@ -171,14 +172,14 @@ module Sidekiq
|
|
171
172
|
#
|
172
173
|
# We only do this if poll_interval_average is unset (the default).
|
173
174
|
def poll_interval_average
|
174
|
-
|
175
|
+
@config[:poll_interval_average] ||= scaled_poll_interval
|
175
176
|
end
|
176
177
|
|
177
178
|
# Calculates an average poll interval based on the number of known Sidekiq processes.
|
178
179
|
# This minimizes a single point of failure by dispersing check-ins but without taxing
|
179
180
|
# Redis if you run many Sidekiq processes.
|
180
181
|
def scaled_poll_interval
|
181
|
-
process_count *
|
182
|
+
process_count * @config[:average_scheduled_poll_interval]
|
182
183
|
end
|
183
184
|
|
184
185
|
def process_count
|
@@ -197,7 +198,7 @@ module Sidekiq
|
|
197
198
|
# to give time for the heartbeat to register (if the poll interval is going to be calculated by the number
|
198
199
|
# of workers), and 5 random seconds to ensure they don't all hit Redis at the same time.
|
199
200
|
total = 0
|
200
|
-
total += INITIAL_WAIT unless
|
201
|
+
total += INITIAL_WAIT unless @config[:poll_interval_average]
|
201
202
|
total += (5 * rand)
|
202
203
|
|
203
204
|
@sleeper.pop(total)
|
data/lib/sidekiq/testing.rb
CHANGED
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "securerandom"
|
4
|
+
require "sidekiq/client"
|
5
|
+
|
6
|
+
module Sidekiq
|
7
|
+
class TransactionAwareClient
|
8
|
+
def initialize(redis_pool)
|
9
|
+
@redis_client = Client.new(redis_pool)
|
10
|
+
end
|
11
|
+
|
12
|
+
def push(item)
|
13
|
+
# pre-allocate the JID so we can return it immediately and
|
14
|
+
# save it to the database as part of the transaction.
|
15
|
+
item["jid"] ||= SecureRandom.hex(12)
|
16
|
+
AfterCommitEverywhere.after_commit { @redis_client.push(item) }
|
17
|
+
item["jid"]
|
18
|
+
end
|
19
|
+
|
20
|
+
##
|
21
|
+
# We don't provide transactionality for push_bulk because we don't want
|
22
|
+
# to hold potentially hundreds of thousands of job records in memory due to
|
23
|
+
# a long running enqueue process.
|
24
|
+
def push_bulk(items)
|
25
|
+
@redis_client.push_bulk(items)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
##
|
31
|
+
# Use `Sidekiq.transactional_push!` in your sidekiq.rb initializer
|
32
|
+
module Sidekiq
|
33
|
+
def self.transactional_push!
|
34
|
+
begin
|
35
|
+
require "after_commit_everywhere"
|
36
|
+
rescue LoadError
|
37
|
+
Sidekiq.logger.error("You need to add after_commit_everywhere to your Gemfile to use Sidekiq's transactional client")
|
38
|
+
raise
|
39
|
+
end
|
40
|
+
|
41
|
+
default_job_options["client_class"] = Sidekiq::TransactionAwareClient
|
42
|
+
Sidekiq::JobUtil::TRANSIENT_ATTRIBUTES << "client_class"
|
43
|
+
true
|
44
|
+
end
|
45
|
+
end
|
data/lib/sidekiq/version.rb
CHANGED
@@ -60,6 +60,19 @@ module Sidekiq
|
|
60
60
|
erb(:dashboard)
|
61
61
|
end
|
62
62
|
|
63
|
+
get "/metrics" do
|
64
|
+
q = Sidekiq::Metrics::Query.new
|
65
|
+
@resultset = q.top_jobs
|
66
|
+
erb(:metrics)
|
67
|
+
end
|
68
|
+
|
69
|
+
get "/metrics/:name" do
|
70
|
+
@name = route_params[:name]
|
71
|
+
q = Sidekiq::Metrics::Query.new
|
72
|
+
@resultset = q.for_job(@name)
|
73
|
+
erb(:metrics_for_job)
|
74
|
+
end
|
75
|
+
|
63
76
|
get "/busy" do
|
64
77
|
erb(:busy)
|
65
78
|
end
|
data/lib/sidekiq/web/helpers.rb
CHANGED
@@ -15,7 +15,7 @@ module Sidekiq
|
|
15
15
|
# so extensions can be localized
|
16
16
|
@strings[lang] ||= settings.locales.each_with_object({}) do |path, global|
|
17
17
|
find_locale_files(lang).each do |file|
|
18
|
-
strs = YAML.
|
18
|
+
strs = YAML.safe_load(File.open(file))
|
19
19
|
global.merge!(strs[lang])
|
20
20
|
end
|
21
21
|
end
|
@@ -148,6 +148,29 @@ module Sidekiq
|
|
148
148
|
@processes ||= Sidekiq::ProcessSet.new
|
149
149
|
end
|
150
150
|
|
151
|
+
# Sorts processes by hostname following the natural sort order so that
|
152
|
+
# 'worker.1' < 'worker.2' < 'worker.10' < 'worker.20'
|
153
|
+
# '2.1.1.1' < '192.168.0.2' < '192.168.0.10'
|
154
|
+
def sorted_processes
|
155
|
+
@sorted_processes ||= begin
|
156
|
+
return processes unless processes.all? { |p| p["hostname"] }
|
157
|
+
|
158
|
+
split_characters = /[._-]/
|
159
|
+
|
160
|
+
padding = processes.flat_map { |p| p["hostname"].split(split_characters) }.map(&:size).max
|
161
|
+
|
162
|
+
processes.to_a.sort_by do |process|
|
163
|
+
process["hostname"].split(split_characters).map do |substring|
|
164
|
+
# Left-pad the substring with '0' if it starts with a number or 'a'
|
165
|
+
# otherwise, so that '25' < 192' < 'a' ('025' < '192' < 'aaa')
|
166
|
+
padding_char = substring[0].match?(/\d/) ? "0" : "a"
|
167
|
+
|
168
|
+
substring.rjust(padding, padding_char)
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
151
174
|
def stats
|
152
175
|
@stats ||= Sidekiq::Stats.new
|
153
176
|
end
|
@@ -301,7 +324,7 @@ module Sidekiq
|
|
301
324
|
end
|
302
325
|
|
303
326
|
def environment_title_prefix
|
304
|
-
environment = Sidekiq
|
327
|
+
environment = Sidekiq[:environment] || ENV["APP_ENV"] || ENV["RAILS_ENV"] || ENV["RACK_ENV"] || "development"
|
305
328
|
|
306
329
|
"[#{environment.upcase}] " unless environment == "production"
|
307
330
|
end
|
data/lib/sidekiq/web.rb
CHANGED
data/lib/sidekiq/worker.rb
CHANGED
@@ -359,7 +359,8 @@ module Sidekiq
|
|
359
359
|
|
360
360
|
def build_client # :nodoc:
|
361
361
|
pool = Thread.current[:sidekiq_via_pool] || get_sidekiq_options["pool"] || Sidekiq.redis_pool
|
362
|
-
Sidekiq::Client
|
362
|
+
client_class = get_sidekiq_options["client_class"] || Sidekiq::Client
|
363
|
+
client_class.new(pool)
|
363
364
|
end
|
364
365
|
end
|
365
366
|
end
|
data/lib/sidekiq.rb
CHANGED
@@ -5,6 +5,7 @@ fail "Sidekiq #{Sidekiq::VERSION} does not support Ruby versions below 2.5.0." i
|
|
5
5
|
|
6
6
|
require "sidekiq/logger"
|
7
7
|
require "sidekiq/client"
|
8
|
+
require "sidekiq/transaction_aware_client"
|
8
9
|
require "sidekiq/worker"
|
9
10
|
require "sidekiq/job"
|
10
11
|
require "sidekiq/redis_connection"
|
@@ -33,7 +34,10 @@ module Sidekiq
|
|
33
34
|
startup: [],
|
34
35
|
quiet: [],
|
35
36
|
shutdown: [],
|
36
|
-
heartbeat
|
37
|
+
# triggers when we fire the first heartbeat on startup OR repairing a network partition
|
38
|
+
heartbeat: [],
|
39
|
+
# triggers on EVERY heartbeat call, every 10 seconds
|
40
|
+
beat: []
|
37
41
|
},
|
38
42
|
dead_max_jobs: 10_000,
|
39
43
|
dead_timeout_in_seconds: 180 * 24 * 60 * 60, # 6 months
|
@@ -52,19 +56,84 @@ module Sidekiq
|
|
52
56
|
puts "Calm down, yo."
|
53
57
|
end
|
54
58
|
|
59
|
+
# config.concurrency = 5
|
60
|
+
def self.concurrency=(val)
|
61
|
+
self[:concurrency] = Integer(val)
|
62
|
+
end
|
63
|
+
|
64
|
+
# config.queues = %w( high default low ) # strict
|
65
|
+
# config.queues = %w( high,3 default,2 low,1 ) # weighted
|
66
|
+
# config.queues = %w( feature1,1 feature2,1 feature3,1 ) # random
|
67
|
+
#
|
68
|
+
# With weighted priority, queue will be checked first (weight / total) of the time.
|
69
|
+
# high will be checked first (3/6) or 50% of the time.
|
70
|
+
# I'd recommend setting weights between 1-10. Weights in the hundreds or thousands
|
71
|
+
# are ridiculous and unnecessarily expensive. You can get random queue ordering
|
72
|
+
# by explicitly setting all weights to 1.
|
73
|
+
def self.queues=(val)
|
74
|
+
self[:queues] = Array(val).each_with_object([]) do |qstr, memo|
|
75
|
+
name, weight = qstr.split(",")
|
76
|
+
self[:strict] = false if weight.to_i > 0
|
77
|
+
[weight.to_i, 1].max.times do
|
78
|
+
memo << name
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
### Private APIs
|
84
|
+
def self.default_error_handler(ex, ctx)
|
85
|
+
logger.warn(dump_json(ctx)) unless ctx.empty?
|
86
|
+
logger.warn("#{ex.class.name}: #{ex.message}")
|
87
|
+
logger.warn(ex.backtrace.join("\n")) unless ex.backtrace.nil?
|
88
|
+
end
|
89
|
+
|
90
|
+
# DEFAULT_ERROR_HANDLER is a constant that allows the default error handler to
|
91
|
+
# be referenced. It must be defined here, after the default_error_handler
|
92
|
+
# method is defined.
|
93
|
+
DEFAULT_ERROR_HANDLER = method(:default_error_handler)
|
94
|
+
|
95
|
+
@config = DEFAULTS.dup
|
55
96
|
def self.options
|
56
|
-
|
97
|
+
logger.warn "`config.options[:key] = value` is deprecated, use `config[:key] = value`: #{caller(1..2)}"
|
98
|
+
@config
|
57
99
|
end
|
58
100
|
|
59
101
|
def self.options=(opts)
|
60
|
-
|
102
|
+
logger.warn "config.options = hash` is deprecated, use `config.merge!(hash)`: #{caller(1..2)}"
|
103
|
+
@config = opts
|
104
|
+
end
|
105
|
+
|
106
|
+
def self.[](key)
|
107
|
+
@config[key]
|
108
|
+
end
|
109
|
+
|
110
|
+
def self.[]=(key, val)
|
111
|
+
@config[key] = val
|
112
|
+
end
|
113
|
+
|
114
|
+
def self.merge!(hash)
|
115
|
+
@config.merge!(hash)
|
116
|
+
end
|
117
|
+
|
118
|
+
def self.fetch(*args, &block)
|
119
|
+
@config.fetch(*args, &block)
|
120
|
+
end
|
121
|
+
|
122
|
+
def self.handle_exception(ex, ctx = {})
|
123
|
+
self[:error_handlers].each do |handler|
|
124
|
+
handler.call(ex, ctx)
|
125
|
+
rescue => ex
|
126
|
+
logger.error "!!! ERROR HANDLER THREW AN ERROR !!!"
|
127
|
+
logger.error ex
|
128
|
+
logger.error ex.backtrace.join("\n") unless ex.backtrace.nil?
|
129
|
+
end
|
61
130
|
end
|
131
|
+
###
|
62
132
|
|
63
133
|
##
|
64
134
|
# Configuration for Sidekiq server, use like:
|
65
135
|
#
|
66
136
|
# Sidekiq.configure_server do |config|
|
67
|
-
# config.redis = { :namespace => 'myapp', :size => 25, :url => 'redis://myhost:8877/0' }
|
68
137
|
# config.server_middleware do |chain|
|
69
138
|
# chain.add MyServerHook
|
70
139
|
# end
|
@@ -77,7 +146,7 @@ module Sidekiq
|
|
77
146
|
# Configuration for Sidekiq client, use like:
|
78
147
|
#
|
79
148
|
# Sidekiq.configure_client do |config|
|
80
|
-
# config.redis = { :
|
149
|
+
# config.redis = { size: 1, url: 'redis://myhost:8877/0' }
|
81
150
|
# end
|
82
151
|
def self.configure_client
|
83
152
|
yield self unless server?
|
@@ -93,7 +162,7 @@ module Sidekiq
|
|
93
162
|
retryable = true
|
94
163
|
begin
|
95
164
|
yield conn
|
96
|
-
rescue
|
165
|
+
rescue RedisConnection.adapter::BaseError => ex
|
97
166
|
# 2550 Failover can cause the server to become a replica, need
|
98
167
|
# to disconnect and reopen the socket to get back to the primary.
|
99
168
|
# 4495 Use the same logic if we have a "Not enough replicas" error from the primary
|
@@ -118,7 +187,7 @@ module Sidekiq
|
|
118
187
|
else
|
119
188
|
conn.info
|
120
189
|
end
|
121
|
-
rescue
|
190
|
+
rescue RedisConnection.adapter::CommandError => ex
|
122
191
|
# 2850 return fake version when INFO command has (probably) been renamed
|
123
192
|
raise unless /unknown command/.match?(ex.message)
|
124
193
|
FAKE_INFO
|
@@ -126,19 +195,19 @@ module Sidekiq
|
|
126
195
|
end
|
127
196
|
|
128
197
|
def self.redis_pool
|
129
|
-
@redis ||=
|
198
|
+
@redis ||= RedisConnection.create
|
130
199
|
end
|
131
200
|
|
132
201
|
def self.redis=(hash)
|
133
202
|
@redis = if hash.is_a?(ConnectionPool)
|
134
203
|
hash
|
135
204
|
else
|
136
|
-
|
205
|
+
RedisConnection.create(hash)
|
137
206
|
end
|
138
207
|
end
|
139
208
|
|
140
209
|
def self.client_middleware
|
141
|
-
@client_chain ||= Middleware::Chain.new
|
210
|
+
@client_chain ||= Middleware::Chain.new(self)
|
142
211
|
yield @client_chain if block_given?
|
143
212
|
@client_chain
|
144
213
|
end
|
@@ -150,7 +219,7 @@ module Sidekiq
|
|
150
219
|
end
|
151
220
|
|
152
221
|
def self.default_server_middleware
|
153
|
-
Middleware::Chain.new
|
222
|
+
Middleware::Chain.new(self)
|
154
223
|
end
|
155
224
|
|
156
225
|
def self.default_worker_options=(hash) # deprecated
|
@@ -179,7 +248,7 @@ module Sidekiq
|
|
179
248
|
# end
|
180
249
|
# end
|
181
250
|
def self.death_handlers
|
182
|
-
|
251
|
+
self[:death_handlers]
|
183
252
|
end
|
184
253
|
|
185
254
|
def self.load_json(string)
|
@@ -209,7 +278,7 @@ module Sidekiq
|
|
209
278
|
|
210
279
|
def self.logger=(logger)
|
211
280
|
if logger.nil?
|
212
|
-
self.logger.
|
281
|
+
self.logger.level = Logger::FATAL
|
213
282
|
return self.logger
|
214
283
|
end
|
215
284
|
|
@@ -232,7 +301,7 @@ module Sidekiq
|
|
232
301
|
#
|
233
302
|
# See sidekiq/scheduled.rb for an in-depth explanation of this value
|
234
303
|
def self.average_scheduled_poll_interval=(interval)
|
235
|
-
|
304
|
+
self[:average_scheduled_poll_interval] = interval
|
236
305
|
end
|
237
306
|
|
238
307
|
# Register a proc to handle any error which occurs within the Sidekiq process.
|
@@ -243,7 +312,7 @@ module Sidekiq
|
|
243
312
|
#
|
244
313
|
# The default error handler logs errors to Sidekiq.logger.
|
245
314
|
def self.error_handlers
|
246
|
-
|
315
|
+
self[:error_handlers]
|
247
316
|
end
|
248
317
|
|
249
318
|
# Register a block to run at a point in the Sidekiq lifecycle.
|
@@ -256,12 +325,12 @@ module Sidekiq
|
|
256
325
|
# end
|
257
326
|
def self.on(event, &block)
|
258
327
|
raise ArgumentError, "Symbols only please: #{event}" unless event.is_a?(Symbol)
|
259
|
-
raise ArgumentError, "Invalid event name: #{event}" unless
|
260
|
-
|
328
|
+
raise ArgumentError, "Invalid event name: #{event}" unless self[:lifecycle_events].key?(event)
|
329
|
+
self[:lifecycle_events][event] << block
|
261
330
|
end
|
262
331
|
|
263
332
|
def self.strict_args!(mode = :raise)
|
264
|
-
|
333
|
+
self[:on_complex_arguments] = mode
|
265
334
|
end
|
266
335
|
|
267
336
|
# We are shutting down Sidekiq but what about threads that
|
data/sidekiq.gemspec
CHANGED
@@ -22,7 +22,7 @@ Gem::Specification.new do |gem|
|
|
22
22
|
"source_code_uri" => "https://github.com/mperham/sidekiq"
|
23
23
|
}
|
24
24
|
|
25
|
-
gem.add_dependency "redis", ">= 4.
|
25
|
+
gem.add_dependency "redis", ">= 4.5.0"
|
26
26
|
gem.add_dependency "connection_pool", ">= 2.2.2"
|
27
27
|
gem.add_dependency "rack", "~> 2.0"
|
28
28
|
end
|
@@ -63,7 +63,7 @@ function addPollingListeners(_event) {
|
|
63
63
|
function addDataToggleListeners(event) {
|
64
64
|
var source = event.target || event.srcElement;
|
65
65
|
var targName = source.getAttribute("data-toggle");
|
66
|
-
var full = document.getElementById(targName
|
66
|
+
var full = document.getElementById(targName);
|
67
67
|
if (full.style.display == "block") {
|
68
68
|
full.style.display = 'none';
|
69
69
|
} else {
|