sidekiq 6.5.9 → 7.0.0.beta1
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 +5 -13
- data/README.md +13 -12
- data/bin/sidekiq +3 -8
- data/bin/sidekiqload +14 -23
- data/lib/sidekiq/api.rb +51 -127
- data/lib/sidekiq/capsule.rb +110 -0
- data/lib/sidekiq/cli.rb +44 -59
- data/lib/sidekiq/client.rb +30 -17
- data/lib/sidekiq/component.rb +1 -0
- data/lib/sidekiq/config.rb +270 -0
- data/lib/sidekiq/deploy.rb +62 -0
- data/lib/sidekiq/embedded.rb +61 -0
- data/lib/sidekiq/fetch.rb +10 -11
- data/lib/sidekiq/job.rb +375 -10
- data/lib/sidekiq/job_logger.rb +1 -1
- data/lib/sidekiq/job_retry.rb +8 -8
- data/lib/sidekiq/job_util.rb +4 -4
- data/lib/sidekiq/launcher.rb +36 -46
- data/lib/sidekiq/logger.rb +1 -26
- data/lib/sidekiq/manager.rb +9 -11
- data/lib/sidekiq/metrics/query.rb +3 -3
- data/lib/sidekiq/metrics/shared.rb +4 -3
- data/lib/sidekiq/metrics/tracking.rb +18 -18
- data/lib/sidekiq/middleware/chain.rb +7 -9
- data/lib/sidekiq/middleware/current_attributes.rb +3 -8
- data/lib/sidekiq/monitor.rb +1 -1
- data/lib/sidekiq/paginator.rb +1 -9
- data/lib/sidekiq/pool.rb +7 -0
- data/lib/sidekiq/processor.rb +17 -26
- data/lib/sidekiq/redis_client_adapter.rb +9 -45
- data/lib/sidekiq/redis_connection.rb +11 -111
- data/lib/sidekiq/scheduled.rb +19 -20
- data/lib/sidekiq/testing.rb +4 -32
- data/lib/sidekiq/transaction_aware_client.rb +4 -5
- data/lib/sidekiq/version.rb +1 -1
- data/lib/sidekiq/web/application.rb +1 -4
- data/lib/sidekiq/web/csrf_protection.rb +1 -1
- data/lib/sidekiq/web/helpers.rb +21 -22
- data/lib/sidekiq/web.rb +2 -17
- data/lib/sidekiq/worker_compatibility_alias.rb +13 -0
- data/lib/sidekiq.rb +52 -274
- data/sidekiq.gemspec +29 -5
- data/web/assets/javascripts/base-charts.js +106 -0
- data/web/assets/javascripts/dashboard-charts.js +166 -0
- data/web/assets/javascripts/dashboard.js +3 -223
- data/web/assets/javascripts/metrics.js +90 -116
- data/web/assets/stylesheets/application-rtl.css +2 -91
- data/web/assets/stylesheets/application.css +21 -296
- data/web/locales/ar.yml +70 -70
- data/web/locales/cs.yml +62 -62
- data/web/locales/da.yml +52 -52
- data/web/locales/de.yml +65 -65
- data/web/locales/el.yml +2 -7
- data/web/locales/en.yml +76 -70
- data/web/locales/es.yml +68 -68
- data/web/locales/fa.yml +65 -65
- data/web/locales/fr.yml +67 -67
- data/web/locales/he.yml +65 -64
- data/web/locales/hi.yml +59 -59
- data/web/locales/it.yml +53 -53
- data/web/locales/ja.yml +64 -68
- data/web/locales/ko.yml +52 -52
- data/web/locales/lt.yml +66 -66
- data/web/locales/nb.yml +61 -61
- data/web/locales/nl.yml +52 -52
- data/web/locales/pl.yml +45 -45
- data/web/locales/pt-br.yml +59 -69
- data/web/locales/pt.yml +51 -51
- data/web/locales/ru.yml +67 -66
- data/web/locales/sv.yml +53 -53
- data/web/locales/ta.yml +60 -60
- data/web/locales/uk.yml +62 -61
- data/web/locales/ur.yml +64 -64
- data/web/locales/vi.yml +67 -67
- data/web/locales/zh-cn.yml +1 -0
- data/web/locales/zh-tw.yml +10 -1
- data/web/views/_footer.erb +5 -2
- data/web/views/busy.erb +1 -6
- data/web/views/dashboard.erb +36 -5
- data/web/views/metrics.erb +30 -19
- data/web/views/metrics_for_job.erb +16 -34
- metadata +60 -37
- data/lib/sidekiq/delay.rb +0 -43
- data/lib/sidekiq/extensions/action_mailer.rb +0 -48
- data/lib/sidekiq/extensions/active_record.rb +0 -43
- data/lib/sidekiq/extensions/class_methods.rb +0 -43
- data/lib/sidekiq/extensions/generic_proxy.rb +0 -33
- data/lib/sidekiq/metrics/deploy.rb +0 -47
- data/lib/sidekiq/worker.rb +0 -370
- data/web/assets/javascripts/graph.js +0 -16
- /data/{LICENSE → LICENSE.txt} +0 -0
data/lib/sidekiq/launcher.rb
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "sidekiq/manager"
|
4
|
-
require "sidekiq/
|
4
|
+
require "sidekiq/capsule"
|
5
5
|
require "sidekiq/scheduled"
|
6
6
|
require "sidekiq/ring_buffer"
|
7
7
|
|
8
8
|
module Sidekiq
|
9
|
-
# The Launcher starts the
|
9
|
+
# The Launcher starts the Capsule Managers, the Poller thread and provides the process heartbeat.
|
10
10
|
class Launcher
|
11
11
|
include Sidekiq::Component
|
12
12
|
|
@@ -16,48 +16,53 @@ module Sidekiq
|
|
16
16
|
proc { "sidekiq" },
|
17
17
|
proc { Sidekiq::VERSION },
|
18
18
|
proc { |me, data| data["tag"] },
|
19
|
-
proc { |me, data| "[#{Processor::WORK_STATE.size} of #{
|
19
|
+
proc { |me, data| "[#{Processor::WORK_STATE.size} of #{me.config.total_concurrency} busy]" },
|
20
20
|
proc { |me, data| "stopping" if me.stopping? }
|
21
21
|
]
|
22
22
|
|
23
|
-
attr_accessor :
|
23
|
+
attr_accessor :managers, :poller
|
24
24
|
|
25
|
-
def initialize(
|
26
|
-
@config =
|
27
|
-
|
28
|
-
@
|
29
|
-
|
25
|
+
def initialize(config, embedded: false)
|
26
|
+
@config = config
|
27
|
+
@embedded = embedded
|
28
|
+
@managers = config.capsules.values.map do |cap|
|
29
|
+
Sidekiq::Manager.new(cap)
|
30
|
+
end
|
31
|
+
@poller = Sidekiq::Scheduled::Poller.new(@config)
|
30
32
|
@done = false
|
31
33
|
end
|
32
34
|
|
33
35
|
def run
|
36
|
+
Sidekiq.freeze!
|
34
37
|
@thread = safe_thread("heartbeat", &method(:start_heartbeat))
|
35
38
|
@poller.start
|
36
|
-
@
|
39
|
+
@managers.each(&:start)
|
37
40
|
end
|
38
41
|
|
39
42
|
# Stops this instance from processing any more jobs,
|
40
43
|
#
|
41
44
|
def quiet
|
45
|
+
return if @done
|
46
|
+
|
42
47
|
@done = true
|
43
|
-
@
|
48
|
+
@managers.each(&:quiet)
|
44
49
|
@poller.terminate
|
50
|
+
fire_event(:quiet, reverse: true)
|
45
51
|
end
|
46
52
|
|
47
53
|
# Shuts down this Sidekiq instance. Waits up to the deadline for all jobs to complete.
|
48
54
|
def stop
|
49
55
|
deadline = ::Process.clock_gettime(::Process::CLOCK_MONOTONIC) + @config[:timeout]
|
50
56
|
|
51
|
-
|
52
|
-
@
|
53
|
-
|
54
|
-
|
55
|
-
|
57
|
+
quiet
|
58
|
+
stoppers = @managers.map do |mgr|
|
59
|
+
Thread.new do
|
60
|
+
mgr.stop(deadline)
|
61
|
+
end
|
62
|
+
end
|
56
63
|
|
57
|
-
|
58
|
-
|
59
|
-
strategy = @config[:fetch]
|
60
|
-
strategy.bulk_requeue([], @config)
|
64
|
+
fire_event(:shutdown, reverse: true)
|
65
|
+
stoppers.each(&:join)
|
61
66
|
|
62
67
|
clear_heartbeat
|
63
68
|
end
|
@@ -68,7 +73,7 @@ module Sidekiq
|
|
68
73
|
|
69
74
|
private unless $TESTING
|
70
75
|
|
71
|
-
BEAT_PAUSE =
|
76
|
+
BEAT_PAUSE = 10
|
72
77
|
|
73
78
|
def start_heartbeat
|
74
79
|
loop do
|
@@ -95,7 +100,7 @@ module Sidekiq
|
|
95
100
|
end
|
96
101
|
|
97
102
|
def heartbeat
|
98
|
-
$0 = PROCTITLES.map { |proc| proc.call(self, to_data) }.compact.join(" ")
|
103
|
+
$0 = PROCTITLES.map { |proc| proc.call(self, to_data) }.compact.join(" ") unless @embedded
|
99
104
|
|
100
105
|
❤
|
101
106
|
end
|
@@ -107,7 +112,7 @@ module Sidekiq
|
|
107
112
|
|
108
113
|
nowdate = Time.now.utc.strftime("%Y-%m-%d")
|
109
114
|
begin
|
110
|
-
|
115
|
+
redis do |conn|
|
111
116
|
conn.pipelined do |pipeline|
|
112
117
|
pipeline.incrby("stat:processed", procd)
|
113
118
|
pipeline.incrby("stat:processed:#{nowdate}", procd)
|
@@ -119,9 +124,7 @@ module Sidekiq
|
|
119
124
|
end
|
120
125
|
end
|
121
126
|
rescue => ex
|
122
|
-
|
123
|
-
# try to handle the exception
|
124
|
-
Sidekiq.logger.warn("Unable to flush stats: #{ex}")
|
127
|
+
logger.warn("Unable to flush stats: #{ex}")
|
125
128
|
end
|
126
129
|
end
|
127
130
|
|
@@ -130,23 +133,10 @@ module Sidekiq
|
|
130
133
|
fails = procd = 0
|
131
134
|
|
132
135
|
begin
|
133
|
-
|
134
|
-
procd = Processor::PROCESSED.reset
|
135
|
-
curstate = Processor::WORK_STATE.dup
|
136
|
-
|
137
|
-
nowdate = Time.now.utc.strftime("%Y-%m-%d")
|
136
|
+
flush_stats
|
138
137
|
|
138
|
+
curstate = Processor::WORK_STATE.dup
|
139
139
|
redis do |conn|
|
140
|
-
conn.multi do |transaction|
|
141
|
-
transaction.incrby("stat:processed", procd)
|
142
|
-
transaction.incrby("stat:processed:#{nowdate}", procd)
|
143
|
-
transaction.expire("stat:processed:#{nowdate}", STATS_TTL)
|
144
|
-
|
145
|
-
transaction.incrby("stat:failed", fails)
|
146
|
-
transaction.incrby("stat:failed:#{nowdate}", fails)
|
147
|
-
transaction.expire("stat:failed:#{nowdate}", STATS_TTL)
|
148
|
-
end
|
149
|
-
|
150
140
|
# work is the current set of executing jobs
|
151
141
|
work_key = "#{key}:work"
|
152
142
|
conn.pipelined do |transaction|
|
@@ -166,7 +156,7 @@ module Sidekiq
|
|
166
156
|
_, exists, _, _, msg = redis { |conn|
|
167
157
|
conn.multi { |transaction|
|
168
158
|
transaction.sadd("processes", [key])
|
169
|
-
transaction.exists
|
159
|
+
transaction.exists(key)
|
170
160
|
transaction.hmset(key, "info", to_json,
|
171
161
|
"busy", curstate.size,
|
172
162
|
"beat", Time.now.to_f,
|
@@ -179,7 +169,7 @@ module Sidekiq
|
|
179
169
|
}
|
180
170
|
|
181
171
|
# first heartbeat or recovering from an outage and need to reestablish our heartbeat
|
182
|
-
fire_event(:heartbeat) unless exists
|
172
|
+
fire_event(:heartbeat) unless exists > 0
|
183
173
|
fire_event(:beat, oneshot: false)
|
184
174
|
|
185
175
|
return unless msg
|
@@ -251,9 +241,9 @@ module Sidekiq
|
|
251
241
|
"started_at" => Time.now.to_f,
|
252
242
|
"pid" => ::Process.pid,
|
253
243
|
"tag" => @config[:tag] || "",
|
254
|
-
"concurrency" => @config
|
255
|
-
"queues" => @config
|
256
|
-
"labels" => @config[:labels],
|
244
|
+
"concurrency" => @config.total_concurrency,
|
245
|
+
"queues" => @config.capsules.values.map { |cap| cap.queues }.flatten.uniq,
|
246
|
+
"labels" => @config[:labels].to_a,
|
257
247
|
"identity" => identity
|
258
248
|
}
|
259
249
|
end
|
data/lib/sidekiq/logger.rb
CHANGED
@@ -31,7 +31,7 @@ module Sidekiq
|
|
31
31
|
"fatal" => 4
|
32
32
|
}
|
33
33
|
LEVELS.default_proc = proc do |_, level|
|
34
|
-
|
34
|
+
puts("Invalid log level: #{level.inspect}")
|
35
35
|
nil
|
36
36
|
end
|
37
37
|
|
@@ -70,36 +70,11 @@ module Sidekiq
|
|
70
70
|
ensure
|
71
71
|
self.local_level = old_local_level
|
72
72
|
end
|
73
|
-
|
74
|
-
# Redefined to check severity against #level, and thus the thread-local level, rather than +@level+.
|
75
|
-
# FIXME: Remove when the minimum Ruby version supports overriding Logger#level.
|
76
|
-
def add(severity, message = nil, progname = nil, &block)
|
77
|
-
severity ||= ::Logger::UNKNOWN
|
78
|
-
progname ||= @progname
|
79
|
-
|
80
|
-
return true if @logdev.nil? || severity < level
|
81
|
-
|
82
|
-
if message.nil?
|
83
|
-
if block
|
84
|
-
message = yield
|
85
|
-
else
|
86
|
-
message = progname
|
87
|
-
progname = @progname
|
88
|
-
end
|
89
|
-
end
|
90
|
-
|
91
|
-
@logdev.write format_message(format_severity(severity), Time.now, progname, message)
|
92
|
-
end
|
93
73
|
end
|
94
74
|
|
95
75
|
class Logger < ::Logger
|
96
76
|
include LoggingUtils
|
97
77
|
|
98
|
-
def initialize(*args, **kwargs)
|
99
|
-
super
|
100
|
-
self.formatter = Sidekiq.log_formatter
|
101
|
-
end
|
102
|
-
|
103
78
|
module Formatters
|
104
79
|
class Base < ::Logger::Formatter
|
105
80
|
def tid
|
data/lib/sidekiq/manager.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "sidekiq/processor"
|
4
|
-
require "sidekiq/fetch"
|
5
4
|
require "set"
|
6
5
|
|
7
6
|
module Sidekiq
|
@@ -23,19 +22,19 @@ module Sidekiq
|
|
23
22
|
include Sidekiq::Component
|
24
23
|
|
25
24
|
attr_reader :workers
|
25
|
+
attr_reader :capsule
|
26
26
|
|
27
|
-
def initialize(
|
28
|
-
@config =
|
29
|
-
|
30
|
-
@count = options[:concurrency] || 10
|
27
|
+
def initialize(capsule)
|
28
|
+
@config = @capsule = capsule
|
29
|
+
@count = capsule.concurrency
|
31
30
|
raise ArgumentError, "Concurrency of #{@count} is not supported" if @count < 1
|
32
31
|
|
33
32
|
@done = false
|
34
33
|
@workers = Set.new
|
34
|
+
@plock = Mutex.new
|
35
35
|
@count.times do
|
36
36
|
@workers << Processor.new(@config, &method(:processor_result))
|
37
37
|
end
|
38
|
-
@plock = Mutex.new
|
39
38
|
end
|
40
39
|
|
41
40
|
def start
|
@@ -46,14 +45,12 @@ module Sidekiq
|
|
46
45
|
return if @done
|
47
46
|
@done = true
|
48
47
|
|
49
|
-
logger.info { "Terminating quiet threads" }
|
48
|
+
logger.info { "Terminating quiet threads for #{capsule.name} capsule" }
|
50
49
|
@workers.each(&:terminate)
|
51
|
-
fire_event(:quiet, reverse: true)
|
52
50
|
end
|
53
51
|
|
54
52
|
def stop(deadline)
|
55
53
|
quiet
|
56
|
-
fire_event(:shutdown, reverse: true)
|
57
54
|
|
58
55
|
# some of the shutdown events can be async,
|
59
56
|
# we don't have any way to know when they're done but
|
@@ -66,6 +63,8 @@ module Sidekiq
|
|
66
63
|
return if @workers.empty?
|
67
64
|
|
68
65
|
hard_shutdown
|
66
|
+
ensure
|
67
|
+
capsule.stop
|
69
68
|
end
|
70
69
|
|
71
70
|
def processor_result(processor, reason = nil)
|
@@ -105,8 +104,7 @@ module Sidekiq
|
|
105
104
|
# contract says that jobs are run AT LEAST once. Process termination
|
106
105
|
# is delayed until we're certain the jobs are back in Redis because
|
107
106
|
# it is worse to lose a job than to run it twice.
|
108
|
-
|
109
|
-
strategy.bulk_requeue(jobs, @config)
|
107
|
+
capsule.fetcher.bulk_requeue(jobs, nil)
|
110
108
|
end
|
111
109
|
|
112
110
|
cleanup.each do |processor|
|
@@ -13,9 +13,9 @@ module Sidekiq
|
|
13
13
|
# NB: all metrics and times/dates are UTC only. We specifically do not
|
14
14
|
# support timezones.
|
15
15
|
class Query
|
16
|
-
def initialize(pool:
|
16
|
+
def initialize(pool: nil, now: Time.now)
|
17
17
|
@time = now.utc
|
18
|
-
@pool = pool
|
18
|
+
@pool = pool || Sidekiq.default_configuration.redis_pool
|
19
19
|
@klass = nil
|
20
20
|
end
|
21
21
|
|
@@ -123,7 +123,7 @@ module Sidekiq
|
|
123
123
|
def series_avg(metric = "ms")
|
124
124
|
series[metric].each_with_object(Hash.new(0)) do |(bucket, value), result|
|
125
125
|
completed = series.dig("p", bucket) - series.dig("f", bucket)
|
126
|
-
result[bucket] =
|
126
|
+
result[bucket] = completed == 0 ? 0 : value.to_f / completed
|
127
127
|
end
|
128
128
|
end
|
129
129
|
end
|
@@ -2,7 +2,8 @@ require "concurrent"
|
|
2
2
|
|
3
3
|
module Sidekiq
|
4
4
|
module Metrics
|
5
|
-
#
|
5
|
+
# This is the only dependency on concurrent-ruby in Sidekiq but it's
|
6
|
+
# mandatory for thread-safety until MRI supports atomic operations on values.
|
6
7
|
Counter = ::Concurrent::AtomicFixnum
|
7
8
|
|
8
9
|
# Implements space-efficient but statistically useful histogram storage.
|
@@ -38,7 +39,6 @@ module Sidekiq
|
|
38
39
|
"65s", "100s", "150s", "225s", "335s",
|
39
40
|
"Slow"
|
40
41
|
]
|
41
|
-
|
42
42
|
FETCH = "GET u16 #0 GET u16 #1 GET u16 #2 GET u16 #3 \
|
43
43
|
GET u16 #4 GET u16 #5 GET u16 #6 GET u16 #7 \
|
44
44
|
GET u16 #8 GET u16 #9 GET u16 #10 GET u16 #11 \
|
@@ -46,6 +46,7 @@ module Sidekiq
|
|
46
46
|
GET u16 #16 GET u16 #17 GET u16 #18 GET u16 #19 \
|
47
47
|
GET u16 #20 GET u16 #21 GET u16 #22 GET u16 #23 \
|
48
48
|
GET u16 #24 GET u16 #25".split
|
49
|
+
HISTOGRAM_TTL = 8 * 60 * 60
|
49
50
|
|
50
51
|
def each
|
51
52
|
buckets.each { |counter| yield counter.value }
|
@@ -86,7 +87,7 @@ module Sidekiq
|
|
86
87
|
end
|
87
88
|
|
88
89
|
conn.bitfield(*cmd) if cmd.size > 3
|
89
|
-
conn.expire(key,
|
90
|
+
conn.expire(key, HISTOGRAM_TTL)
|
90
91
|
key
|
91
92
|
end
|
92
93
|
end
|
@@ -48,8 +48,8 @@ module Sidekiq
|
|
48
48
|
end
|
49
49
|
end
|
50
50
|
|
51
|
-
LONG_TERM = 90 * 24 * 60 * 60
|
52
|
-
MID_TERM = 7 * 24 * 60 * 60
|
51
|
+
# LONG_TERM = 90 * 24 * 60 * 60
|
52
|
+
# MID_TERM = 7 * 24 * 60 * 60
|
53
53
|
SHORT_TERM = 8 * 60 * 60
|
54
54
|
|
55
55
|
def flush(time = Time.now)
|
@@ -59,12 +59,13 @@ module Sidekiq
|
|
59
59
|
return if procd == 0 && fails == 0
|
60
60
|
|
61
61
|
now = time.utc
|
62
|
-
nowdate = now.strftime("%Y%m%d")
|
63
|
-
nowhour = now.strftime("%Y%m%d|%-H")
|
62
|
+
# nowdate = now.strftime("%Y%m%d")
|
63
|
+
# nowhour = now.strftime("%Y%m%d|%-H")
|
64
64
|
nowmin = now.strftime("%Y%m%d|%-H:%-M")
|
65
65
|
count = 0
|
66
66
|
|
67
67
|
redis do |conn|
|
68
|
+
# persist fine-grained histogram data
|
68
69
|
if grams.size > 0
|
69
70
|
conn.pipelined do |pipe|
|
70
71
|
grams.each do |_, gram|
|
@@ -73,15 +74,16 @@ module Sidekiq
|
|
73
74
|
end
|
74
75
|
end
|
75
76
|
|
77
|
+
# persist coarse grained execution count + execution millis.
|
78
|
+
# note as of today we don't use or do anything with the
|
79
|
+
# daily or hourly rollups.
|
76
80
|
[
|
77
|
-
["j", jobs, nowdate, LONG_TERM],
|
78
|
-
["j", jobs, nowhour, MID_TERM],
|
81
|
+
# ["j", jobs, nowdate, LONG_TERM],
|
82
|
+
# ["j", jobs, nowhour, MID_TERM],
|
79
83
|
["j", jobs, nowmin, SHORT_TERM]
|
80
84
|
].each do |prefix, data, bucket, ttl|
|
81
|
-
# Quietly seed the new 7.0 stats format so migration is painless.
|
82
85
|
conn.pipelined do |xa|
|
83
86
|
stats = "#{prefix}|#{bucket}"
|
84
|
-
# logger.debug "Flushing metrics #{stats}"
|
85
87
|
data.each_pair do |key, value|
|
86
88
|
xa.hincrby stats, key, value
|
87
89
|
count += 1
|
@@ -89,7 +91,7 @@ module Sidekiq
|
|
89
91
|
xa.expire(stats, ttl)
|
90
92
|
end
|
91
93
|
end
|
92
|
-
logger.
|
94
|
+
logger.debug "Flushed #{count} metrics"
|
93
95
|
count
|
94
96
|
end
|
95
97
|
end
|
@@ -121,14 +123,12 @@ module Sidekiq
|
|
121
123
|
end
|
122
124
|
end
|
123
125
|
|
124
|
-
|
125
|
-
Sidekiq.
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
exec.flush
|
132
|
-
end
|
126
|
+
Sidekiq.configure_server do |config|
|
127
|
+
exec = Sidekiq::Metrics::ExecutionTracker.new(config)
|
128
|
+
config.server_middleware do |chain|
|
129
|
+
chain.add Sidekiq::Metrics::Middleware, exec
|
130
|
+
end
|
131
|
+
config.on(:beat) do
|
132
|
+
exec.flush
|
133
133
|
end
|
134
134
|
end
|
@@ -80,15 +80,6 @@ module Sidekiq
|
|
80
80
|
class Chain
|
81
81
|
include Enumerable
|
82
82
|
|
83
|
-
# A unique instance of the middleware chain is created for
|
84
|
-
# each job executed in order to be thread-safe.
|
85
|
-
# @param copy [Sidekiq::Middleware::Chain] New instance of Chain
|
86
|
-
# @returns nil
|
87
|
-
def initialize_copy(copy)
|
88
|
-
copy.instance_variable_set(:@entries, entries.dup)
|
89
|
-
nil
|
90
|
-
end
|
91
|
-
|
92
83
|
# Iterate through each middleware in the chain
|
93
84
|
def each(&block)
|
94
85
|
entries.each(&block)
|
@@ -105,6 +96,12 @@ module Sidekiq
|
|
105
96
|
@entries ||= []
|
106
97
|
end
|
107
98
|
|
99
|
+
def copy_for(capsule)
|
100
|
+
chain = Sidekiq::Middleware::Chain.new(capsule)
|
101
|
+
chain.instance_variable_set(:@entries, entries.dup)
|
102
|
+
chain
|
103
|
+
end
|
104
|
+
|
108
105
|
# Remove all middleware matching the given Class
|
109
106
|
# @param klass [Class]
|
110
107
|
def remove(klass)
|
@@ -152,6 +149,7 @@ module Sidekiq
|
|
152
149
|
def exists?(klass)
|
153
150
|
any? { |entry| entry.klass == klass }
|
154
151
|
end
|
152
|
+
alias_method :include?, :exists?
|
155
153
|
|
156
154
|
# @return [Boolean] if the chain contains no middleware
|
157
155
|
def empty?
|
@@ -50,14 +50,9 @@ module Sidekiq
|
|
50
50
|
end
|
51
51
|
end
|
52
52
|
|
53
|
-
def self.persist(klass)
|
54
|
-
|
55
|
-
|
56
|
-
end
|
57
|
-
Sidekiq.configure_server do |config|
|
58
|
-
config.client_middleware.add Save, klass.to_s
|
59
|
-
config.server_middleware.add Load, klass.to_s
|
60
|
-
end
|
53
|
+
def self.persist(klass, config = Sidekiq.default_configuration)
|
54
|
+
config.client_middleware.add Save, klass.to_s
|
55
|
+
config.server_middleware.add Load, klass.to_s
|
61
56
|
end
|
62
57
|
end
|
63
58
|
end
|
data/lib/sidekiq/monitor.rb
CHANGED
@@ -101,7 +101,7 @@ class Sidekiq::Monitor
|
|
101
101
|
tags = [
|
102
102
|
process["tag"],
|
103
103
|
process["labels"],
|
104
|
-
(
|
104
|
+
(process["quiet"] == "true" ? "quiet" : nil)
|
105
105
|
].flatten.compact
|
106
106
|
tags.any? ? "[#{tags.join("] [")}]" : nil
|
107
107
|
end
|
data/lib/sidekiq/paginator.rb
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
module Sidekiq
|
4
4
|
module Paginator
|
5
5
|
def page(key, pageidx = 1, page_size = 25, opts = nil)
|
6
|
-
current_page =
|
6
|
+
current_page = pageidx.to_i < 1 ? 1 : pageidx.to_i
|
7
7
|
pageidx = current_page - 1
|
8
8
|
total_size = 0
|
9
9
|
items = []
|
@@ -43,13 +43,5 @@ module Sidekiq
|
|
43
43
|
end
|
44
44
|
end
|
45
45
|
end
|
46
|
-
|
47
|
-
def page_items(items, pageidx = 1, page_size = 25)
|
48
|
-
current_page = (pageidx.to_i < 1) ? 1 : pageidx.to_i
|
49
|
-
pageidx = current_page - 1
|
50
|
-
starting = pageidx * page_size
|
51
|
-
items = items.to_a
|
52
|
-
[current_page, items.size, items[starting, page_size]]
|
53
|
-
end
|
54
46
|
end
|
55
47
|
end
|
data/lib/sidekiq/pool.rb
ADDED
data/lib/sidekiq/processor.rb
CHANGED
@@ -26,18 +26,18 @@ module Sidekiq
|
|
26
26
|
|
27
27
|
attr_reader :thread
|
28
28
|
attr_reader :job
|
29
|
+
attr_reader :capsule
|
29
30
|
|
30
|
-
def initialize(
|
31
|
+
def initialize(capsule, &block)
|
32
|
+
@config = @capsule = capsule
|
31
33
|
@callback = block
|
32
34
|
@down = false
|
33
35
|
@done = false
|
34
36
|
@job = nil
|
35
37
|
@thread = nil
|
36
|
-
@
|
37
|
-
@
|
38
|
-
@
|
39
|
-
@job_logger = (options[:job_logger] || Sidekiq::JobLogger).new
|
40
|
-
@retrier = Sidekiq::JobRetry.new(options)
|
38
|
+
@reloader = Sidekiq.default_configuration[:reloader]
|
39
|
+
@job_logger = (capsule.config[:job_logger] || Sidekiq::JobLogger).new(logger)
|
40
|
+
@retrier = Sidekiq::JobRetry.new(capsule)
|
41
41
|
end
|
42
42
|
|
43
43
|
def terminate(wait = false)
|
@@ -59,12 +59,16 @@ module Sidekiq
|
|
59
59
|
end
|
60
60
|
|
61
61
|
def start
|
62
|
-
@thread ||= safe_thread("processor", &method(:run))
|
62
|
+
@thread ||= safe_thread("#{config.name}/processor", &method(:run))
|
63
63
|
end
|
64
64
|
|
65
65
|
private unless $TESTING
|
66
66
|
|
67
67
|
def run
|
68
|
+
# By setting this thread-local, Sidekiq.redis will access +Sidekiq::Capsule#redis_pool+
|
69
|
+
# instead of the global pool in +Sidekiq::Config#redis_pool+.
|
70
|
+
Thread.current[:sidekiq_capsule] = @capsule
|
71
|
+
|
68
72
|
process_one until @done
|
69
73
|
@callback.call(self)
|
70
74
|
rescue Sidekiq::Shutdown
|
@@ -80,7 +84,7 @@ module Sidekiq
|
|
80
84
|
end
|
81
85
|
|
82
86
|
def get_one
|
83
|
-
uow =
|
87
|
+
uow = capsule.fetcher.retrieve_work
|
84
88
|
if @down
|
85
89
|
logger.info { "Redis is online, #{::Process.clock_gettime(::Process::CLOCK_MONOTONIC) - @down} sec downtime" }
|
86
90
|
@down = nil
|
@@ -129,7 +133,7 @@ module Sidekiq
|
|
129
133
|
# the Reloader. It handles code loading, db connection management, etc.
|
130
134
|
# Effectively this block denotes a "unit of work" to Rails.
|
131
135
|
@reloader.call do
|
132
|
-
klass =
|
136
|
+
klass = Object.const_get(job_hash["class"])
|
133
137
|
inst = klass.new
|
134
138
|
inst.jid = job_hash["jid"]
|
135
139
|
@retrier.local(inst, jobstr, queue) do
|
@@ -153,11 +157,11 @@ module Sidekiq
|
|
153
157
|
rescue => ex
|
154
158
|
handle_exception(ex, {context: "Invalid JSON for job", jobstr: jobstr})
|
155
159
|
now = Time.now.to_f
|
156
|
-
|
160
|
+
redis do |conn|
|
157
161
|
conn.multi do |xa|
|
158
162
|
xa.zadd("dead", now.to_s, jobstr)
|
159
|
-
xa.zremrangebyscore("dead", "-inf", now - config[:dead_timeout_in_seconds])
|
160
|
-
xa.zremrangebyrank("dead", 0, - config[:dead_max_jobs])
|
163
|
+
xa.zremrangebyscore("dead", "-inf", now - @capsule.config[:dead_timeout_in_seconds])
|
164
|
+
xa.zremrangebyrank("dead", 0, - @capsule.config[:dead_max_jobs])
|
161
165
|
end
|
162
166
|
end
|
163
167
|
return uow.acknowledge
|
@@ -166,7 +170,7 @@ module Sidekiq
|
|
166
170
|
ack = false
|
167
171
|
begin
|
168
172
|
dispatch(job_hash, queue, jobstr) do |inst|
|
169
|
-
|
173
|
+
config.server_middleware.invoke(inst, job_hash, queue) do
|
170
174
|
execute_job(inst, job_hash["args"])
|
171
175
|
end
|
172
176
|
end
|
@@ -269,18 +273,5 @@ module Sidekiq
|
|
269
273
|
PROCESSED.incr
|
270
274
|
end
|
271
275
|
end
|
272
|
-
|
273
|
-
def constantize(str)
|
274
|
-
return Object.const_get(str) unless str.include?("::")
|
275
|
-
|
276
|
-
names = str.split("::")
|
277
|
-
names.shift if names.empty? || names.first.empty?
|
278
|
-
|
279
|
-
names.inject(Object) do |constant, name|
|
280
|
-
# the false flag limits search for name to under the constant namespace
|
281
|
-
# which mimics Rails' behaviour
|
282
|
-
constant.const_get(name, false)
|
283
|
-
end
|
284
|
-
end
|
285
276
|
end
|
286
277
|
end
|