sidekiq 6.5.12 → 7.3.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (123) hide show
  1. checksums.yaml +4 -4
  2. data/Changes.md +327 -20
  3. data/README.md +43 -35
  4. data/bin/multi_queue_bench +271 -0
  5. data/bin/sidekiq +3 -8
  6. data/bin/sidekiqload +213 -118
  7. data/bin/sidekiqmon +3 -0
  8. data/lib/active_job/queue_adapters/sidekiq_adapter.rb +88 -0
  9. data/lib/generators/sidekiq/job_generator.rb +2 -0
  10. data/lib/sidekiq/api.rb +243 -162
  11. data/lib/sidekiq/capsule.rb +132 -0
  12. data/lib/sidekiq/cli.rb +60 -75
  13. data/lib/sidekiq/client.rb +87 -38
  14. data/lib/sidekiq/component.rb +26 -1
  15. data/lib/sidekiq/config.rb +311 -0
  16. data/lib/sidekiq/deploy.rb +64 -0
  17. data/lib/sidekiq/embedded.rb +63 -0
  18. data/lib/sidekiq/fetch.rb +11 -14
  19. data/lib/sidekiq/iterable_job.rb +55 -0
  20. data/lib/sidekiq/job/interrupt_handler.rb +24 -0
  21. data/lib/sidekiq/job/iterable/active_record_enumerator.rb +53 -0
  22. data/lib/sidekiq/job/iterable/csv_enumerator.rb +47 -0
  23. data/lib/sidekiq/job/iterable/enumerators.rb +135 -0
  24. data/lib/sidekiq/job/iterable.rb +294 -0
  25. data/lib/sidekiq/job.rb +382 -10
  26. data/lib/sidekiq/job_logger.rb +8 -7
  27. data/lib/sidekiq/job_retry.rb +42 -19
  28. data/lib/sidekiq/job_util.rb +53 -15
  29. data/lib/sidekiq/launcher.rb +71 -65
  30. data/lib/sidekiq/logger.rb +2 -27
  31. data/lib/sidekiq/manager.rb +9 -11
  32. data/lib/sidekiq/metrics/query.rb +9 -4
  33. data/lib/sidekiq/metrics/shared.rb +21 -9
  34. data/lib/sidekiq/metrics/tracking.rb +40 -26
  35. data/lib/sidekiq/middleware/chain.rb +19 -18
  36. data/lib/sidekiq/middleware/current_attributes.rb +85 -20
  37. data/lib/sidekiq/middleware/modules.rb +2 -0
  38. data/lib/sidekiq/monitor.rb +18 -4
  39. data/lib/sidekiq/paginator.rb +2 -2
  40. data/lib/sidekiq/processor.rb +62 -57
  41. data/lib/sidekiq/rails.rb +17 -10
  42. data/lib/sidekiq/redis_client_adapter.rb +31 -71
  43. data/lib/sidekiq/redis_connection.rb +44 -115
  44. data/lib/sidekiq/ring_buffer.rb +2 -0
  45. data/lib/sidekiq/scheduled.rb +22 -23
  46. data/lib/sidekiq/systemd.rb +2 -0
  47. data/lib/sidekiq/testing.rb +37 -46
  48. data/lib/sidekiq/transaction_aware_client.rb +11 -5
  49. data/lib/sidekiq/version.rb +6 -1
  50. data/lib/sidekiq/web/action.rb +29 -7
  51. data/lib/sidekiq/web/application.rb +82 -28
  52. data/lib/sidekiq/web/csrf_protection.rb +10 -7
  53. data/lib/sidekiq/web/helpers.rb +104 -43
  54. data/lib/sidekiq/web/router.rb +5 -2
  55. data/lib/sidekiq/web.rb +70 -17
  56. data/lib/sidekiq/worker_compatibility_alias.rb +13 -0
  57. data/lib/sidekiq.rb +78 -274
  58. data/sidekiq.gemspec +12 -10
  59. data/web/assets/javascripts/application.js +44 -0
  60. data/web/assets/javascripts/base-charts.js +106 -0
  61. data/web/assets/javascripts/dashboard-charts.js +192 -0
  62. data/web/assets/javascripts/dashboard.js +11 -233
  63. data/web/assets/javascripts/metrics.js +151 -115
  64. data/web/assets/stylesheets/application-dark.css +4 -0
  65. data/web/assets/stylesheets/application-rtl.css +10 -89
  66. data/web/assets/stylesheets/application.css +56 -296
  67. data/web/locales/ar.yml +70 -70
  68. data/web/locales/cs.yml +62 -62
  69. data/web/locales/da.yml +60 -53
  70. data/web/locales/de.yml +65 -65
  71. data/web/locales/el.yml +2 -7
  72. data/web/locales/en.yml +78 -71
  73. data/web/locales/es.yml +68 -68
  74. data/web/locales/fa.yml +65 -65
  75. data/web/locales/fr.yml +80 -67
  76. data/web/locales/gd.yml +98 -0
  77. data/web/locales/he.yml +65 -64
  78. data/web/locales/hi.yml +59 -59
  79. data/web/locales/it.yml +85 -54
  80. data/web/locales/ja.yml +67 -70
  81. data/web/locales/ko.yml +52 -52
  82. data/web/locales/lt.yml +66 -66
  83. data/web/locales/nb.yml +61 -61
  84. data/web/locales/nl.yml +52 -52
  85. data/web/locales/pl.yml +45 -45
  86. data/web/locales/pt-br.yml +78 -69
  87. data/web/locales/pt.yml +51 -51
  88. data/web/locales/ru.yml +67 -66
  89. data/web/locales/sv.yml +53 -53
  90. data/web/locales/ta.yml +60 -60
  91. data/web/locales/tr.yml +100 -0
  92. data/web/locales/uk.yml +85 -61
  93. data/web/locales/ur.yml +64 -64
  94. data/web/locales/vi.yml +67 -67
  95. data/web/locales/zh-cn.yml +20 -19
  96. data/web/locales/zh-tw.yml +10 -2
  97. data/web/views/_footer.erb +17 -2
  98. data/web/views/_job_info.erb +18 -2
  99. data/web/views/_metrics_period_select.erb +12 -0
  100. data/web/views/_paging.erb +2 -0
  101. data/web/views/_poll_link.erb +1 -1
  102. data/web/views/_summary.erb +7 -7
  103. data/web/views/busy.erb +46 -35
  104. data/web/views/dashboard.erb +28 -7
  105. data/web/views/filtering.erb +6 -0
  106. data/web/views/layout.erb +6 -6
  107. data/web/views/metrics.erb +47 -26
  108. data/web/views/metrics_for_job.erb +43 -71
  109. data/web/views/morgue.erb +6 -10
  110. data/web/views/queue.erb +10 -14
  111. data/web/views/queues.erb +9 -3
  112. data/web/views/retries.erb +5 -9
  113. data/web/views/scheduled.erb +12 -13
  114. metadata +53 -39
  115. data/lib/sidekiq/delay.rb +0 -43
  116. data/lib/sidekiq/extensions/action_mailer.rb +0 -48
  117. data/lib/sidekiq/extensions/active_record.rb +0 -43
  118. data/lib/sidekiq/extensions/class_methods.rb +0 -43
  119. data/lib/sidekiq/extensions/generic_proxy.rb +0 -33
  120. data/lib/sidekiq/metrics/deploy.rb +0 -47
  121. data/lib/sidekiq/worker.rb +0 -370
  122. data/web/assets/javascripts/graph.js +0 -16
  123. /data/{LICENSE → LICENSE.txt} +0 -0
@@ -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?
@@ -168,23 +166,26 @@ module Sidekiq
168
166
 
169
167
  # Used by Sidekiq to execute the middleware at runtime
170
168
  # @api private
171
- def invoke(*args)
169
+ def invoke(*args, &block)
172
170
  return yield if empty?
173
171
 
174
172
  chain = retrieve
175
- traverse_chain = proc do
176
- if chain.empty?
177
- yield
178
- else
179
- chain.shift.call(*args, &traverse_chain)
173
+ traverse(chain, 0, args, &block)
174
+ end
175
+
176
+ private
177
+
178
+ def traverse(chain, index, args, &block)
179
+ if index >= chain.size
180
+ yield
181
+ else
182
+ chain[index].call(*args) do
183
+ traverse(chain, index + 1, args, &block)
180
184
  end
181
185
  end
182
- traverse_chain.call
183
186
  end
184
187
  end
185
188
 
186
- private
187
-
188
189
  # Represents each link in the middleware chain
189
190
  # @api private
190
191
  class Entry
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support/current_attributes"
2
4
 
3
5
  module Sidekiq
@@ -7,56 +9,119 @@ module Sidekiq
7
9
  # This can be useful for multi-tenancy, i18n locale, timezone, any implicit
8
10
  # per-request attribute. See +ActiveSupport::CurrentAttributes+.
9
11
  #
12
+ # For multiple current attributes, pass an array of current attributes.
13
+ #
10
14
  # @example
11
15
  #
12
16
  # # in your initializer
13
17
  # require "sidekiq/middleware/current_attributes"
14
18
  # Sidekiq::CurrentAttributes.persist("Myapp::Current")
19
+ # # or multiple current attributes
20
+ # Sidekiq::CurrentAttributes.persist(["Myapp::Current", "Myapp::OtherCurrent"])
15
21
  #
16
22
  module CurrentAttributes
17
23
  class Save
18
24
  include Sidekiq::ClientMiddleware
19
25
 
20
- def initialize(cattr)
21
- @strklass = cattr
26
+ def initialize(cattrs)
27
+ @cattrs = cattrs
22
28
  end
23
29
 
24
30
  def call(_, job, _, _)
25
- attrs = @strklass.constantize.attributes
26
- if attrs.any?
27
- if job.has_key?("cattr")
28
- job["cattr"].merge!(attrs)
29
- else
30
- job["cattr"] = attrs
31
+ @cattrs.each do |(key, strklass)|
32
+ if !job.has_key?(key)
33
+ attrs = strklass.constantize.attributes
34
+ # Retries can push the job N times, we don't
35
+ # want retries to reset cattr. #5692, #5090
36
+ if attrs.any?
37
+ # Older rails has a bug that `CurrentAttributes#attributes` always returns
38
+ # the same hash instance. We need to dup it to avoid being accidentally mutated.
39
+ job[key] = if returns_same_object?
40
+ attrs.dup
41
+ else
42
+ attrs
43
+ end
44
+ end
31
45
  end
32
46
  end
33
47
  yield
34
48
  end
49
+
50
+ private
51
+
52
+ def returns_same_object?
53
+ ActiveSupport::VERSION::MAJOR < 8 ||
54
+ (ActiveSupport::VERSION::MAJOR == 8 && ActiveSupport::VERSION::MINOR == 0)
55
+ end
35
56
  end
36
57
 
37
58
  class Load
38
59
  include Sidekiq::ServerMiddleware
39
60
 
40
- def initialize(cattr)
41
- @strklass = cattr
61
+ def initialize(cattrs)
62
+ @cattrs = cattrs
42
63
  end
43
64
 
44
65
  def call(_, job, _, &block)
45
- if job.has_key?("cattr")
46
- @strklass.constantize.set(job["cattr"], &block)
47
- else
48
- yield
66
+ klass_attrs = {}
67
+
68
+ @cattrs.each do |(key, strklass)|
69
+ next unless job.has_key?(key)
70
+
71
+ klass_attrs[strklass.constantize] = job[key]
72
+ end
73
+
74
+ wrap(klass_attrs.to_a, &block)
75
+ end
76
+
77
+ private
78
+
79
+ def wrap(klass_attrs, &block)
80
+ klass, attrs = klass_attrs.shift
81
+ return block.call unless klass
82
+
83
+ retried = false
84
+
85
+ begin
86
+ klass.set(attrs) do
87
+ wrap(klass_attrs, &block)
88
+ end
89
+ rescue NoMethodError
90
+ raise if retried
91
+
92
+ # It is possible that the `CurrentAttributes` definition
93
+ # was changed before the job started processing.
94
+ attrs = attrs.select { |attr| klass.respond_to?(attr) }
95
+ retried = true
96
+ retry
49
97
  end
50
98
  end
51
99
  end
52
100
 
53
- def self.persist(klass)
54
- Sidekiq.configure_client do |config|
55
- config.client_middleware.add Save, klass.to_s
101
+ class << self
102
+ def persist(klass_or_array, config = Sidekiq.default_configuration)
103
+ cattrs = build_cattrs_hash(klass_or_array)
104
+
105
+ config.client_middleware.add Save, cattrs
106
+ config.server_middleware.prepend Load, cattrs
107
+ end
108
+
109
+ private
110
+
111
+ def build_cattrs_hash(klass_or_array)
112
+ if klass_or_array.is_a?(Array)
113
+ {}.tap do |hash|
114
+ klass_or_array.each_with_index do |klass, index|
115
+ hash[key_at(index)] = klass.to_s
116
+ end
117
+ end
118
+ else
119
+ {key_at(0) => klass_or_array.to_s}
120
+ end
56
121
  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
122
+
123
+ def key_at(index)
124
+ (index == 0) ? "cattr" : "cattr_#{index}"
60
125
  end
61
126
  end
62
127
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Sidekiq
2
4
  # Server-side middleware must import this Module in order
3
5
  # to get access to server resources during `call`.
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
4
  require "fileutils"
4
5
  require "sidekiq/api"
@@ -16,8 +17,6 @@ class Sidekiq::Monitor
16
17
  return
17
18
  end
18
19
  send(section)
19
- rescue => e
20
- abort "Couldn't get status: #{e}"
21
20
  end
22
21
 
23
22
  def all
@@ -49,10 +48,25 @@ class Sidekiq::Monitor
49
48
  def processes
50
49
  puts "---- Processes (#{process_set.size}) ----"
51
50
  process_set.each_with_index do |process, index|
51
+ # Keep compatibility with legacy versions since we don't want to break sidekiqmon during rolling upgrades or downgrades.
52
+ #
53
+ # Before:
54
+ # ["default", "critical"]
55
+ #
56
+ # After:
57
+ # {"default" => 1, "critical" => 10}
58
+ queues =
59
+ if process["weights"]
60
+ process["weights"].sort_by { |queue| queue[0] }.map { |capsule| capsule.map { |name, weight| (weight > 0) ? "#{name}: #{weight}" : name }.join(", ") }
61
+ else
62
+ process["queues"].sort
63
+ end
64
+
52
65
  puts "#{process["identity"]} #{tags_for(process)}"
53
66
  puts " Started: #{Time.at(process["started_at"])} (#{time_ago(process["started_at"])})"
54
67
  puts " Threads: #{process["concurrency"]} (#{process["busy"]} busy)"
55
- puts " Queues: #{split_multiline(process["queues"].sort, pad: 11)}"
68
+ puts " Queues: #{split_multiline(queues, pad: 11)}"
69
+ puts " Version: #{process["version"] || "Unknown"}" if process["version"] != Sidekiq::VERSION
56
70
  puts "" unless (index + 1) == process_set.size
57
71
  end
58
72
  end
@@ -85,7 +99,7 @@ class Sidekiq::Monitor
85
99
  pad = opts[:pad] || 0
86
100
  max_length = opts[:max_length] || (80 - pad)
87
101
  out = []
88
- line = ""
102
+ line = +""
89
103
  values.each do |value|
90
104
  if (line.length + value.length) > max_length
91
105
  out << line
@@ -19,9 +19,9 @@ module Sidekiq
19
19
  total_size, items = conn.multi { |transaction|
20
20
  transaction.zcard(key)
21
21
  if rev
22
- transaction.zrevrange(key, starting, ending, withscores: true)
22
+ transaction.zrange(key, starting, ending, "REV", "withscores")
23
23
  else
24
- transaction.zrange(key, starting, ending, withscores: true)
24
+ transaction.zrange(key, starting, ending, "withscores")
25
25
  end
26
26
  }
27
27
  [current_page, total_size, items]
@@ -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(options, &block)
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
- @config = options
37
- @strategy = options[:fetch]
38
- @reloader = options[:reloader] || proc { |&block| block.call }
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(capsule.config)
40
+ @retrier = Sidekiq::JobRetry.new(capsule)
41
41
  end
42
42
 
43
43
  def terminate(wait = false)
@@ -58,13 +58,21 @@ module Sidekiq
58
58
  @thread.value if wait
59
59
  end
60
60
 
61
+ def stopping?
62
+ @done
63
+ end
64
+
61
65
  def start
62
- @thread ||= safe_thread("processor", &method(:run))
66
+ @thread ||= safe_thread("#{config.name}/processor", &method(:run))
63
67
  end
64
68
 
65
69
  private unless $TESTING
66
70
 
67
71
  def run
72
+ # By setting this thread-local, Sidekiq.redis will access +Sidekiq::Capsule#redis_pool+
73
+ # instead of the global pool in +Sidekiq::Config#redis_pool+.
74
+ Thread.current[:sidekiq_capsule] = @capsule
75
+
68
76
  process_one until @done
69
77
  @callback.call(self)
70
78
  rescue Sidekiq::Shutdown
@@ -80,7 +88,7 @@ module Sidekiq
80
88
  end
81
89
 
82
90
  def get_one
83
- uow = @strategy.retrieve_work
91
+ uow = capsule.fetcher.retrieve_work
84
92
  if @down
85
93
  logger.info { "Redis is online, #{::Process.clock_gettime(::Process::CLOCK_MONOTONIC) - @down} sec downtime" }
86
94
  @down = nil
@@ -129,11 +137,12 @@ module Sidekiq
129
137
  # the Reloader. It handles code loading, db connection management, etc.
130
138
  # Effectively this block denotes a "unit of work" to Rails.
131
139
  @reloader.call do
132
- klass = constantize(job_hash["class"])
133
- inst = klass.new
134
- inst.jid = job_hash["jid"]
135
- @retrier.local(inst, jobstr, queue) do
136
- yield inst
140
+ klass = Object.const_get(job_hash["class"])
141
+ instance = klass.new
142
+ instance.jid = job_hash["jid"]
143
+ instance._context = self
144
+ @retrier.local(instance, jobstr, queue) do
145
+ yield instance
137
146
  end
138
147
  end
139
148
  end
@@ -142,6 +151,11 @@ module Sidekiq
142
151
  end
143
152
  end
144
153
 
154
+ IGNORE_SHUTDOWN_INTERRUPTS = {Sidekiq::Shutdown => :never}
155
+ private_constant :IGNORE_SHUTDOWN_INTERRUPTS
156
+ ALLOW_SHUTDOWN_INTERRUPTS = {Sidekiq::Shutdown => :immediate}
157
+ private_constant :ALLOW_SHUTDOWN_INTERRUPTS
158
+
145
159
  def process(uow)
146
160
  jobstr = uow.job
147
161
  queue = uow.queue_name
@@ -153,53 +167,57 @@ module Sidekiq
153
167
  rescue => ex
154
168
  handle_exception(ex, {context: "Invalid JSON for job", jobstr: jobstr})
155
169
  now = Time.now.to_f
156
- config.redis do |conn|
170
+ redis do |conn|
157
171
  conn.multi do |xa|
158
172
  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])
173
+ xa.zremrangebyscore("dead", "-inf", now - @capsule.config[:dead_timeout_in_seconds])
174
+ xa.zremrangebyrank("dead", 0, - @capsule.config[:dead_max_jobs])
161
175
  end
162
176
  end
163
177
  return uow.acknowledge
164
178
  end
165
179
 
166
180
  ack = false
167
- begin
168
- dispatch(job_hash, queue, jobstr) do |inst|
169
- @config.server_middleware.invoke(inst, job_hash, queue) do
170
- execute_job(inst, job_hash["args"])
181
+ Thread.handle_interrupt(IGNORE_SHUTDOWN_INTERRUPTS) do
182
+ Thread.handle_interrupt(ALLOW_SHUTDOWN_INTERRUPTS) do
183
+ dispatch(job_hash, queue, jobstr) do |instance|
184
+ config.server_middleware.invoke(instance, job_hash, queue) do
185
+ execute_job(instance, job_hash["args"])
186
+ end
171
187
  end
188
+ ack = true
189
+ rescue Sidekiq::Shutdown
190
+ # Had to force kill this job because it didn't finish
191
+ # within the timeout. Don't acknowledge the work since
192
+ # we didn't properly finish it.
193
+ rescue Sidekiq::JobRetry::Skip => s
194
+ # Skip means we handled this error elsewhere. We don't
195
+ # need to log or report the error.
196
+ ack = true
197
+ raise s
198
+ rescue Sidekiq::JobRetry::Handled => h
199
+ # this is the common case: job raised error and Sidekiq::JobRetry::Handled
200
+ # signals that we created a retry successfully. We can acknowledge the job.
201
+ ack = true
202
+ e = h.cause || h
203
+ handle_exception(e, {context: "Job raised exception", job: job_hash})
204
+ raise e
205
+ rescue Exception => ex
206
+ # Unexpected error! This is very bad and indicates an exception that got past
207
+ # the retry subsystem (e.g. network partition). We won't acknowledge the job
208
+ # so it can be rescued when using Sidekiq Pro.
209
+ handle_exception(ex, {context: "Internal exception!", job: job_hash, jobstr: jobstr})
210
+ raise ex
172
211
  end
173
- ack = true
174
- rescue Sidekiq::Shutdown
175
- # Had to force kill this job because it didn't finish
176
- # within the timeout. Don't acknowledge the work since
177
- # we didn't properly finish it.
178
- rescue Sidekiq::JobRetry::Handled => h
179
- # this is the common case: job raised error and Sidekiq::JobRetry::Handled
180
- # signals that we created a retry successfully. We can acknowlege the job.
181
- ack = true
182
- e = h.cause || h
183
- handle_exception(e, {context: "Job raised exception", job: job_hash})
184
- raise e
185
- rescue Exception => ex
186
- # Unexpected error! This is very bad and indicates an exception that got past
187
- # the retry subsystem (e.g. network partition). We won't acknowledge the job
188
- # so it can be rescued when using Sidekiq Pro.
189
- handle_exception(ex, {context: "Internal exception!", job: job_hash, jobstr: jobstr})
190
- raise ex
191
212
  ensure
192
213
  if ack
193
- # We don't want a shutdown signal to interrupt job acknowledgment.
194
- Thread.handle_interrupt(Sidekiq::Shutdown => :never) do
195
- uow.acknowledge
196
- end
214
+ uow.acknowledge
197
215
  end
198
216
  end
199
217
  end
200
218
 
201
- def execute_job(inst, cloned_args)
202
- inst.perform(*cloned_args)
219
+ def execute_job(instance, cloned_args)
220
+ instance.perform(*cloned_args)
203
221
  end
204
222
 
205
223
  # Ruby doesn't provide atomic counters out of the box so we'll
@@ -269,18 +287,5 @@ module Sidekiq
269
287
  PROCESSED.incr
270
288
  end
271
289
  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
290
  end
286
291
  end
data/lib/sidekiq/rails.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "sidekiq/job"
4
+ require "rails"
4
5
 
5
6
  module Sidekiq
6
7
  class Rails < ::Rails::Engine
@@ -10,7 +11,8 @@ module Sidekiq
10
11
  end
11
12
 
12
13
  def call
13
- @app.reloader.wrap do
14
+ params = (::Rails::VERSION::STRING >= "7.1") ? {source: "job.sidekiq"} : {}
15
+ @app.reloader.wrap(**params) do
14
16
  yield
15
17
  end
16
18
  end
@@ -18,11 +20,15 @@ module Sidekiq
18
20
  def inspect
19
21
  "#<Sidekiq::Rails::Reloader @app=#{@app.class.name}>"
20
22
  end
23
+
24
+ def to_hash
25
+ {app: @app.class.name}
26
+ end
21
27
  end
22
28
 
23
29
  # By including the Options module, we allow AJs to directly control sidekiq features
24
30
  # via the *sidekiq_options* class method and, for instance, not use AJ's retry system.
25
- # AJ retries don't show up in the Sidekiq UI Retries tab, save any error data, can't be
31
+ # AJ retries don't show up in the Sidekiq UI Retries tab, don't save any error data, can't be
26
32
  # manually retried, don't automatically die, etc.
27
33
  #
28
34
  # class SomeJob < ActiveJob::Base
@@ -33,15 +39,16 @@ module Sidekiq
33
39
  # end
34
40
  initializer "sidekiq.active_job_integration" do
35
41
  ActiveSupport.on_load(:active_job) do
42
+ require "active_job/queue_adapters/sidekiq_adapter"
43
+
36
44
  include ::Sidekiq::Job::Options unless respond_to?(:sidekiq_options)
37
45
  end
38
46
  end
39
47
 
40
- config.before_configuration do
41
- dep = ActiveSupport::Deprecation.new("7.0", "Sidekiq")
42
- dep.deprecate_methods(Sidekiq.singleton_class,
43
- default_worker_options: :default_job_options,
44
- "default_worker_options=": :default_job_options=)
48
+ initializer "sidekiq.backtrace_cleaner" do
49
+ Sidekiq.configure_server do |config|
50
+ config[:backtrace_cleaner] = ->(backtrace) { ::Rails.backtrace_cleaner.clean(backtrace) }
51
+ end
45
52
  end
46
53
 
47
54
  # This hook happens after all initializers are run, just before returning
@@ -55,10 +62,10 @@ module Sidekiq
55
62
  # This is the integration code necessary so that if a job uses `Rails.logger.info "Hello"`,
56
63
  # it will appear in the Sidekiq console with all of the job context.
57
64
  unless ::Rails.logger == config.logger || ::ActiveSupport::Logger.logger_outputs_to?(::Rails.logger, $stdout)
58
- if ::Rails::VERSION::STRING < "7.1"
59
- ::Rails.logger.extend(::ActiveSupport::Logger.broadcast(config.logger))
60
- else
65
+ if ::Rails.logger.respond_to?(:broadcast_to)
61
66
  ::Rails.logger.broadcast_to(config.logger)
67
+ else
68
+ ::Rails.logger.extend(::ActiveSupport::Logger.broadcast(config.logger))
62
69
  end
63
70
  end
64
71
  end