sidekiq 5.2.5 → 6.0.3
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/.circleci/config.yml +82 -0
- data/.gitignore +0 -2
- data/.standard.yml +20 -0
- data/6.0-Upgrade.md +72 -0
- data/COMM-LICENSE +11 -9
- data/Changes.md +136 -0
- data/Ent-2.0-Upgrade.md +37 -0
- data/Ent-Changes.md +32 -1
- data/Gemfile +12 -17
- data/Gemfile.lock +196 -0
- data/Pro-5.0-Upgrade.md +25 -0
- data/Pro-Changes.md +26 -2
- data/README.md +19 -31
- data/Rakefile +5 -4
- data/bin/sidekiqload +33 -25
- data/bin/sidekiqmon +8 -0
- data/lib/generators/sidekiq/templates/worker_test.rb.erb +1 -1
- data/lib/generators/sidekiq/worker_generator.rb +20 -12
- data/lib/sidekiq/api.rb +230 -214
- data/lib/sidekiq/cli.rb +111 -174
- data/lib/sidekiq/client.rb +55 -46
- data/lib/sidekiq/delay.rb +5 -6
- data/lib/sidekiq/exception_handler.rb +10 -12
- data/lib/sidekiq/extensions/action_mailer.rb +10 -20
- data/lib/sidekiq/extensions/active_record.rb +9 -7
- data/lib/sidekiq/extensions/class_methods.rb +9 -7
- data/lib/sidekiq/extensions/generic_proxy.rb +4 -4
- data/lib/sidekiq/fetch.rb +11 -12
- data/lib/sidekiq/job_logger.rb +45 -7
- data/lib/sidekiq/job_retry.rb +71 -60
- data/lib/sidekiq/launcher.rb +57 -51
- data/lib/sidekiq/logger.rb +165 -0
- data/lib/sidekiq/manager.rb +7 -9
- data/lib/sidekiq/middleware/chain.rb +14 -4
- data/lib/sidekiq/middleware/i18n.rb +5 -7
- data/lib/sidekiq/monitor.rb +133 -0
- data/lib/sidekiq/paginator.rb +18 -14
- data/lib/sidekiq/processor.rb +83 -75
- data/lib/sidekiq/rails.rb +23 -29
- data/lib/sidekiq/redis_connection.rb +31 -37
- data/lib/sidekiq/scheduled.rb +28 -29
- data/lib/sidekiq/testing/inline.rb +2 -1
- data/lib/sidekiq/testing.rb +34 -23
- data/lib/sidekiq/util.rb +17 -16
- data/lib/sidekiq/version.rb +2 -1
- data/lib/sidekiq/web/action.rb +14 -10
- data/lib/sidekiq/web/application.rb +64 -66
- data/lib/sidekiq/web/helpers.rb +89 -71
- data/lib/sidekiq/web/router.rb +17 -14
- data/lib/sidekiq/web.rb +41 -49
- data/lib/sidekiq/worker.rb +129 -97
- data/lib/sidekiq.rb +61 -42
- data/sidekiq.gemspec +16 -16
- data/web/assets/javascripts/dashboard.js +4 -23
- data/web/assets/stylesheets/application-dark.css +125 -0
- data/web/assets/stylesheets/application.css +9 -0
- data/web/assets/stylesheets/bootstrap.css +1 -1
- data/web/locales/de.yml +14 -2
- data/web/locales/ja.yml +2 -1
- data/web/views/_job_info.erb +2 -1
- data/web/views/busy.erb +4 -1
- data/web/views/dead.erb +2 -2
- data/web/views/layout.erb +1 -0
- data/web/views/morgue.erb +4 -1
- data/web/views/queue.erb +10 -1
- data/web/views/queues.erb +1 -1
- data/web/views/retries.erb +4 -1
- data/web/views/retry.erb +2 -2
- data/web/views/scheduled.erb +4 -1
- metadata +21 -32
- data/.travis.yml +0 -17
- data/Appraisals +0 -9
- data/bin/sidekiqctl +0 -237
- data/gemfiles/rails_4.gemfile +0 -31
- data/gemfiles/rails_5.gemfile +0 -31
- data/lib/sidekiq/core_ext.rb +0 -1
- data/lib/sidekiq/logging.rb +0 -122
- data/lib/sidekiq/middleware/server/active_record.rb +0 -23
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
#
|
3
4
|
# Simple middleware to save the current locale and restore it when the job executes.
|
4
5
|
# Use it by requiring it in your initializer:
|
@@ -9,19 +10,16 @@ module Sidekiq::Middleware::I18n
|
|
9
10
|
# Get the current locale and store it in the message
|
10
11
|
# to be sent to Sidekiq.
|
11
12
|
class Client
|
12
|
-
def call(
|
13
|
-
msg[
|
13
|
+
def call(_worker, msg, _queue, _redis)
|
14
|
+
msg["locale"] ||= I18n.locale
|
14
15
|
yield
|
15
16
|
end
|
16
17
|
end
|
17
18
|
|
18
19
|
# Pull the msg locale out and set the current thread to use it.
|
19
20
|
class Server
|
20
|
-
def call(
|
21
|
-
I18n.
|
22
|
-
yield
|
23
|
-
ensure
|
24
|
-
I18n.locale = I18n.default_locale
|
21
|
+
def call(_worker, msg, _queue, &block)
|
22
|
+
I18n.with_locale(msg.fetch("locale", I18n.default_locale), &block)
|
25
23
|
end
|
26
24
|
end
|
27
25
|
end
|
@@ -0,0 +1,133 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "fileutils"
|
4
|
+
require "sidekiq/api"
|
5
|
+
|
6
|
+
class Sidekiq::Monitor
|
7
|
+
class Status
|
8
|
+
VALID_SECTIONS = %w[all version overview processes queues]
|
9
|
+
COL_PAD = 2
|
10
|
+
|
11
|
+
def display(section = nil)
|
12
|
+
section ||= "all"
|
13
|
+
unless VALID_SECTIONS.include? section
|
14
|
+
puts "I don't know how to check the status of '#{section}'!"
|
15
|
+
puts "Try one of these: #{VALID_SECTIONS.join(", ")}"
|
16
|
+
return
|
17
|
+
end
|
18
|
+
send(section)
|
19
|
+
rescue => e
|
20
|
+
puts "Couldn't get status: #{e}"
|
21
|
+
end
|
22
|
+
|
23
|
+
def all
|
24
|
+
version
|
25
|
+
puts
|
26
|
+
overview
|
27
|
+
puts
|
28
|
+
processes
|
29
|
+
puts
|
30
|
+
queues
|
31
|
+
end
|
32
|
+
|
33
|
+
def version
|
34
|
+
puts "Sidekiq #{Sidekiq::VERSION}"
|
35
|
+
puts Time.now.utc
|
36
|
+
end
|
37
|
+
|
38
|
+
def overview
|
39
|
+
puts "---- Overview ----"
|
40
|
+
puts " Processed: #{delimit stats.processed}"
|
41
|
+
puts " Failed: #{delimit stats.failed}"
|
42
|
+
puts " Busy: #{delimit stats.workers_size}"
|
43
|
+
puts " Enqueued: #{delimit stats.enqueued}"
|
44
|
+
puts " Retries: #{delimit stats.retry_size}"
|
45
|
+
puts " Scheduled: #{delimit stats.scheduled_size}"
|
46
|
+
puts " Dead: #{delimit stats.dead_size}"
|
47
|
+
end
|
48
|
+
|
49
|
+
def processes
|
50
|
+
puts "---- Processes (#{process_set.size}) ----"
|
51
|
+
process_set.each_with_index do |process, index|
|
52
|
+
puts "#{process["identity"]} #{tags_for(process)}"
|
53
|
+
puts " Started: #{Time.at(process["started_at"])} (#{time_ago(process["started_at"])})"
|
54
|
+
puts " Threads: #{process["concurrency"]} (#{process["busy"]} busy)"
|
55
|
+
puts " Queues: #{split_multiline(process["queues"].sort, pad: 11)}"
|
56
|
+
puts "" unless (index + 1) == process_set.size
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def queues
|
61
|
+
puts "---- Queues (#{queue_data.size}) ----"
|
62
|
+
columns = {
|
63
|
+
name: [:ljust, (["name"] + queue_data.map(&:name)).map(&:length).max + COL_PAD],
|
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],
|
66
|
+
}
|
67
|
+
columns.each { |col, (dir, width)| print col.to_s.upcase.public_send(dir, width) }
|
68
|
+
puts
|
69
|
+
queue_data.each do |q|
|
70
|
+
columns.each do |col, (dir, width)|
|
71
|
+
print q.send(col).public_send(dir, width)
|
72
|
+
end
|
73
|
+
puts
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
private
|
78
|
+
|
79
|
+
def delimit(number)
|
80
|
+
number.to_s.reverse.scan(/.{1,3}/).join(",").reverse
|
81
|
+
end
|
82
|
+
|
83
|
+
def split_multiline(values, opts = {})
|
84
|
+
return "none" unless values
|
85
|
+
pad = opts[:pad] || 0
|
86
|
+
max_length = opts[:max_length] || (80 - pad)
|
87
|
+
out = []
|
88
|
+
line = ""
|
89
|
+
values.each do |value|
|
90
|
+
if (line.length + value.length) > max_length
|
91
|
+
out << line
|
92
|
+
line = " " * pad
|
93
|
+
end
|
94
|
+
line << value + ", "
|
95
|
+
end
|
96
|
+
out << line[0..-3]
|
97
|
+
out.join("\n")
|
98
|
+
end
|
99
|
+
|
100
|
+
def tags_for(process)
|
101
|
+
tags = [
|
102
|
+
process["tag"],
|
103
|
+
process["labels"],
|
104
|
+
(process["quiet"] == "true" ? "quiet" : nil),
|
105
|
+
].flatten.compact
|
106
|
+
tags.any? ? "[#{tags.join("] [")}]" : nil
|
107
|
+
end
|
108
|
+
|
109
|
+
def time_ago(timestamp)
|
110
|
+
seconds = Time.now - Time.at(timestamp)
|
111
|
+
return "just now" if seconds < 60
|
112
|
+
return "a minute ago" if seconds < 120
|
113
|
+
return "#{seconds.floor / 60} minutes ago" if seconds < 3600
|
114
|
+
return "an hour ago" if seconds < 7200
|
115
|
+
"#{seconds.floor / 60 / 60} hours ago"
|
116
|
+
end
|
117
|
+
|
118
|
+
QUEUE_STRUCT = Struct.new(:name, :size, :latency)
|
119
|
+
def queue_data
|
120
|
+
@queue_data ||= Sidekiq::Queue.all.map { |q|
|
121
|
+
QUEUE_STRUCT.new(q.name, q.size.to_s, sprintf("%#.2f", q.latency))
|
122
|
+
}
|
123
|
+
end
|
124
|
+
|
125
|
+
def process_set
|
126
|
+
@process_set ||= Sidekiq::ProcessSet.new
|
127
|
+
end
|
128
|
+
|
129
|
+
def stats
|
130
|
+
@stats ||= Sidekiq::Stats.new
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
data/lib/sidekiq/paginator.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module Sidekiq
|
3
4
|
module Paginator
|
4
|
-
|
5
|
-
def page(key, pageidx=1, page_size=25, opts=nil)
|
5
|
+
def page(key, pageidx = 1, page_size = 25, opts = nil)
|
6
6
|
current_page = pageidx.to_i < 1 ? 1 : pageidx.to_i
|
7
7
|
pageidx = current_page - 1
|
8
8
|
total_size = 0
|
@@ -12,32 +12,36 @@ module Sidekiq
|
|
12
12
|
|
13
13
|
Sidekiq.redis do |conn|
|
14
14
|
type = conn.type(key)
|
15
|
+
rev = opts && opts[:reverse]
|
15
16
|
|
16
17
|
case type
|
17
|
-
when
|
18
|
-
|
19
|
-
total_size, items = conn.multi do
|
18
|
+
when "zset"
|
19
|
+
total_size, items = conn.multi {
|
20
20
|
conn.zcard(key)
|
21
21
|
if rev
|
22
|
-
conn.zrevrange(key, starting, ending, :
|
22
|
+
conn.zrevrange(key, starting, ending, with_scores: true)
|
23
23
|
else
|
24
|
-
conn.zrange(key, starting, ending, :
|
24
|
+
conn.zrange(key, starting, ending, with_scores: true)
|
25
25
|
end
|
26
|
-
|
26
|
+
}
|
27
27
|
[current_page, total_size, items]
|
28
|
-
when
|
29
|
-
total_size, items = conn.multi
|
28
|
+
when "list"
|
29
|
+
total_size, items = conn.multi {
|
30
30
|
conn.llen(key)
|
31
|
-
|
32
|
-
|
31
|
+
if rev
|
32
|
+
conn.lrange(key, -ending - 1, -starting - 1)
|
33
|
+
else
|
34
|
+
conn.lrange(key, starting, ending)
|
35
|
+
end
|
36
|
+
}
|
37
|
+
items.reverse! if rev
|
33
38
|
[current_page, total_size, items]
|
34
|
-
when
|
39
|
+
when "none"
|
35
40
|
[1, 0, []]
|
36
41
|
else
|
37
42
|
raise "can't page a #{type}"
|
38
43
|
end
|
39
44
|
end
|
40
45
|
end
|
41
|
-
|
42
46
|
end
|
43
47
|
end
|
data/lib/sidekiq/processor.rb
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
2
|
+
|
3
|
+
require "sidekiq/util"
|
4
|
+
require "sidekiq/fetch"
|
5
|
+
require "sidekiq/job_logger"
|
6
|
+
require "sidekiq/job_retry"
|
7
7
|
|
8
8
|
module Sidekiq
|
9
9
|
##
|
@@ -23,7 +23,6 @@ module Sidekiq
|
|
23
23
|
# to replace itself and exits.
|
24
24
|
#
|
25
25
|
class Processor
|
26
|
-
|
27
26
|
include Util
|
28
27
|
|
29
28
|
attr_reader :thread
|
@@ -37,19 +36,19 @@ module Sidekiq
|
|
37
36
|
@thread = nil
|
38
37
|
@strategy = (mgr.options[:fetch] || Sidekiq::BasicFetch).new(mgr.options)
|
39
38
|
@reloader = Sidekiq.options[:reloader]
|
40
|
-
@
|
39
|
+
@job_logger = (mgr.options[:job_logger] || Sidekiq::JobLogger).new
|
41
40
|
@retrier = Sidekiq::JobRetry.new
|
42
41
|
end
|
43
42
|
|
44
|
-
def terminate(wait=false)
|
43
|
+
def terminate(wait = false)
|
45
44
|
@done = true
|
46
|
-
return
|
45
|
+
return unless @thread
|
47
46
|
@thread.value if wait
|
48
47
|
end
|
49
48
|
|
50
|
-
def kill(wait=false)
|
49
|
+
def kill(wait = false)
|
51
50
|
@done = true
|
52
|
-
return
|
51
|
+
return unless @thread
|
53
52
|
# unlike the other actors, terminate does not wait
|
54
53
|
# for the thread to finish because we don't know how
|
55
54
|
# long the job will take to finish. Instead we
|
@@ -66,16 +65,12 @@ module Sidekiq
|
|
66
65
|
private unless $TESTING
|
67
66
|
|
68
67
|
def run
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
@mgr.processor_stopped(self)
|
76
|
-
rescue Exception => ex
|
77
|
-
@mgr.processor_died(self, ex)
|
78
|
-
end
|
68
|
+
process_one until @done
|
69
|
+
@mgr.processor_stopped(self)
|
70
|
+
rescue Sidekiq::Shutdown
|
71
|
+
@mgr.processor_stopped(self)
|
72
|
+
rescue Exception => ex
|
73
|
+
@mgr.processor_died(self, ex)
|
79
74
|
end
|
80
75
|
|
81
76
|
def process_one
|
@@ -85,14 +80,15 @@ module Sidekiq
|
|
85
80
|
end
|
86
81
|
|
87
82
|
def get_one
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
rescue Sidekiq::Shutdown
|
93
|
-
rescue => ex
|
94
|
-
handle_fetch_exception(ex)
|
83
|
+
work = @strategy.retrieve_work
|
84
|
+
if @down
|
85
|
+
logger.info { "Redis is online, #{::Process.clock_gettime(::Process::CLOCK_MONOTONIC) - @down} sec downtime" }
|
86
|
+
@down = nil
|
95
87
|
end
|
88
|
+
work
|
89
|
+
rescue Sidekiq::Shutdown
|
90
|
+
rescue => ex
|
91
|
+
handle_fetch_exception(ex)
|
96
92
|
end
|
97
93
|
|
98
94
|
def fetch
|
@@ -106,7 +102,7 @@ module Sidekiq
|
|
106
102
|
end
|
107
103
|
|
108
104
|
def handle_fetch_exception(ex)
|
109
|
-
|
105
|
+
unless @down
|
110
106
|
@down = ::Process.clock_gettime(::Process::CLOCK_MONOTONIC)
|
111
107
|
logger.error("Error fetching job: #{ex}")
|
112
108
|
handle_exception(ex)
|
@@ -115,25 +111,28 @@ module Sidekiq
|
|
115
111
|
nil
|
116
112
|
end
|
117
113
|
|
118
|
-
def dispatch(job_hash, queue)
|
114
|
+
def dispatch(job_hash, queue, jobstr)
|
119
115
|
# since middleware can mutate the job hash
|
120
|
-
# we clone
|
116
|
+
# we need to clone it to report the original
|
121
117
|
# job structure to the Web UI
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
118
|
+
# or to push back to redis when retrying.
|
119
|
+
# To avoid costly and, most of the time, useless cloning here,
|
120
|
+
# we pass original String of JSON to respected methods
|
121
|
+
# to re-parse it there if we need access to the original, untouched job
|
122
|
+
|
123
|
+
@job_logger.prepare(job_hash) do
|
124
|
+
@retrier.global(jobstr, queue) do
|
125
|
+
@job_logger.call(job_hash, queue) do
|
126
|
+
stats(jobstr, queue) do
|
128
127
|
# Rails 5 requires a Reloader to wrap code execution. In order to
|
129
128
|
# constantize the worker and instantiate an instance, we have to call
|
130
129
|
# the Reloader. It handles code loading, db connection management, etc.
|
131
130
|
# Effectively this block denotes a "unit of work" to Rails.
|
132
131
|
@reloader.call do
|
133
|
-
klass
|
132
|
+
klass = constantize(job_hash["class"])
|
134
133
|
worker = klass.new
|
135
|
-
worker.jid = job_hash[
|
136
|
-
@retrier.local(worker,
|
134
|
+
worker.jid = job_hash["jid"]
|
135
|
+
@retrier.local(worker, jobstr, queue) do
|
137
136
|
yield worker
|
138
137
|
end
|
139
138
|
end
|
@@ -147,37 +146,49 @@ module Sidekiq
|
|
147
146
|
jobstr = work.job
|
148
147
|
queue = work.queue_name
|
149
148
|
|
150
|
-
|
149
|
+
# Treat malformed JSON as a special case: job goes straight to the morgue.
|
150
|
+
job_hash = nil
|
151
151
|
begin
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
DeadSet.new.kill(jobstr, notify_failure: false)
|
160
|
-
ack = true
|
161
|
-
raise
|
162
|
-
end
|
152
|
+
job_hash = Sidekiq.load_json(jobstr)
|
153
|
+
rescue => ex
|
154
|
+
handle_exception(ex, {context: "Invalid JSON for job", jobstr: jobstr})
|
155
|
+
# we can't notify because the job isn't a valid hash payload.
|
156
|
+
DeadSet.new.kill(jobstr, notify_failure: false)
|
157
|
+
return work.acknowledge
|
158
|
+
end
|
163
159
|
|
164
|
-
|
165
|
-
|
160
|
+
ack = false
|
161
|
+
begin
|
162
|
+
dispatch(job_hash, queue, jobstr) do |worker|
|
166
163
|
Sidekiq.server_middleware.invoke(worker, job_hash, queue) do
|
167
|
-
execute_job(worker,
|
164
|
+
execute_job(worker, job_hash["args"])
|
168
165
|
end
|
169
166
|
end
|
167
|
+
ack = true
|
170
168
|
rescue Sidekiq::Shutdown
|
171
169
|
# Had to force kill this job because it didn't finish
|
172
170
|
# within the timeout. Don't acknowledge the work since
|
173
171
|
# we didn't properly finish it.
|
174
|
-
|
172
|
+
rescue Sidekiq::JobRetry::Handled => h
|
173
|
+
# this is the common case: job raised error and Sidekiq::JobRetry::Handled
|
174
|
+
# signals that we created a retry successfully. We can acknowlege the job.
|
175
|
+
ack = true
|
176
|
+
e = h.cause || h
|
177
|
+
handle_exception(e, {context: "Job raised exception", job: job_hash, jobstr: jobstr})
|
178
|
+
raise e
|
175
179
|
rescue Exception => ex
|
176
|
-
|
177
|
-
|
180
|
+
# Unexpected error! This is very bad and indicates an exception that got past
|
181
|
+
# the retry subsystem (e.g. network partition). We won't acknowledge the job
|
182
|
+
# so it can be rescued when using Sidekiq Pro.
|
183
|
+
handle_exception(ex, {context: "Internal exception!", job: job_hash, jobstr: jobstr})
|
178
184
|
raise e
|
179
185
|
ensure
|
180
|
-
|
186
|
+
if ack
|
187
|
+
# We don't want a shutdown signal to interrupt job acknowledgment.
|
188
|
+
Thread.handle_interrupt(Sidekiq::Shutdown => :never) do
|
189
|
+
work.acknowledge
|
190
|
+
end
|
191
|
+
end
|
181
192
|
end
|
182
193
|
end
|
183
194
|
|
@@ -194,12 +205,16 @@ module Sidekiq
|
|
194
205
|
@lock = Mutex.new
|
195
206
|
end
|
196
207
|
|
197
|
-
def incr(amount=1)
|
198
|
-
@lock.synchronize { @value
|
208
|
+
def incr(amount = 1)
|
209
|
+
@lock.synchronize { @value += amount }
|
199
210
|
end
|
200
211
|
|
201
212
|
def reset
|
202
|
-
@lock.synchronize {
|
213
|
+
@lock.synchronize {
|
214
|
+
val = @value
|
215
|
+
@value = 0
|
216
|
+
val
|
217
|
+
}
|
203
218
|
end
|
204
219
|
end
|
205
220
|
|
@@ -235,9 +250,8 @@ module Sidekiq
|
|
235
250
|
FAILURE = Counter.new
|
236
251
|
WORKER_STATE = SharedWorkerState.new
|
237
252
|
|
238
|
-
def stats(
|
239
|
-
tid
|
240
|
-
WORKER_STATE.set(tid, {:queue => queue, :payload => job_hash, :run_at => Time.now.to_i })
|
253
|
+
def stats(jobstr, queue)
|
254
|
+
WORKER_STATE.set(tid, {queue: queue, payload: jobstr, run_at: Time.now.to_i})
|
241
255
|
|
242
256
|
begin
|
243
257
|
yield
|
@@ -250,23 +264,17 @@ module Sidekiq
|
|
250
264
|
end
|
251
265
|
end
|
252
266
|
|
253
|
-
# Deep clone the arguments passed to the worker so that if
|
254
|
-
# the job fails, what is pushed back onto Redis hasn't
|
255
|
-
# been mutated by the worker.
|
256
|
-
def cloned(thing)
|
257
|
-
Marshal.load(Marshal.dump(thing))
|
258
|
-
end
|
259
|
-
|
260
267
|
def constantize(str)
|
261
|
-
|
268
|
+
return Object.const_get(str) unless str.include?("::")
|
269
|
+
|
270
|
+
names = str.split("::")
|
262
271
|
names.shift if names.empty? || names.first.empty?
|
263
272
|
|
264
273
|
names.inject(Object) do |constant, name|
|
265
274
|
# the false flag limits search for name to under the constant namespace
|
266
275
|
# which mimics Rails' behaviour
|
267
|
-
constant.
|
276
|
+
constant.const_get(name, false)
|
268
277
|
end
|
269
278
|
end
|
270
|
-
|
271
279
|
end
|
272
280
|
end
|
data/lib/sidekiq/rails.rb
CHANGED
@@ -1,35 +1,35 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "sidekiq/worker"
|
4
|
+
|
3
5
|
module Sidekiq
|
4
6
|
class Rails < ::Rails::Engine
|
5
|
-
#
|
6
|
-
#
|
7
|
+
# By including the Options module, we allow AJs to directly control sidekiq features
|
8
|
+
# via the *sidekiq_options* class method and, for instance, not use AJ's retry system.
|
9
|
+
# AJ retries don't show up in the Sidekiq UI Retries tab, save any error data, can't be
|
10
|
+
# manually retried, don't automatically die, etc.
|
7
11
|
#
|
8
|
-
#
|
9
|
-
#
|
10
|
-
#
|
11
|
-
#
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
end
|
12
|
+
# class SomeJob < ActiveJob::Base
|
13
|
+
# queue_as :default
|
14
|
+
# sidekiq_options retry: 3, backtrace: 10
|
15
|
+
# def perform
|
16
|
+
# end
|
17
|
+
# end
|
18
|
+
initializer "sidekiq.active_job_integration" do
|
19
|
+
ActiveSupport.on_load(:active_job) do
|
20
|
+
include ::Sidekiq::Worker::Options unless respond_to?(:sidekiq_options)
|
18
21
|
end
|
19
22
|
end
|
20
23
|
|
24
|
+
# This hook happens after all initializers are run, just before returning
|
25
|
+
# from config/environment.rb back to sidekiq/cli.rb.
|
26
|
+
# We have to add the reloader after initialize to see if cache_classes has
|
27
|
+
# been turned on.
|
28
|
+
#
|
29
|
+
# None of this matters on the client-side, only within the Sidekiq process itself.
|
21
30
|
config.after_initialize do
|
22
|
-
# This hook happens after all initializers are run, just before returning
|
23
|
-
# from config/environment.rb back to sidekiq/cli.rb.
|
24
|
-
# We have to add the reloader after initialize to see if cache_classes has
|
25
|
-
# been turned on.
|
26
|
-
#
|
27
|
-
# None of this matters on the client-side, only within the Sidekiq process itself.
|
28
|
-
#
|
29
31
|
Sidekiq.configure_server do |_|
|
30
|
-
|
31
|
-
Sidekiq.options[:reloader] = Sidekiq::Rails::Reloader.new
|
32
|
-
end
|
32
|
+
Sidekiq.options[:reloader] = Sidekiq::Rails::Reloader.new
|
33
33
|
end
|
34
34
|
end
|
35
35
|
|
@@ -48,11 +48,5 @@ module Sidekiq
|
|
48
48
|
"#<Sidekiq::Rails::Reloader @app=#{@app.class.name}>"
|
49
49
|
end
|
50
50
|
end
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
if defined?(::Rails) && ::Rails::VERSION::MAJOR < 4
|
55
|
-
$stderr.puts("**************************************************")
|
56
|
-
$stderr.puts("⛔️ WARNING: Sidekiq server is no longer supported by Rails 3.2 - please ensure your server/workers are updated")
|
57
|
-
$stderr.puts("**************************************************")
|
51
|
+
end
|
58
52
|
end
|